iOS 在 UITableViewCell 中以编程方式设置 UIImageView 约束在滚动 tableview 时变得混乱

Posted

技术标签:

【中文标题】iOS 在 UITableViewCell 中以编程方式设置 UIImageView 约束在滚动 tableview 时变得混乱【英文标题】:iOS setting UIImageView constraints programmatically in UITableViewCell gets messed up while scrolling the tableview 【发布时间】:2017-11-28 12:23:08 【问题描述】:

我以编程方式在UITableViewCell 内更改UIImageView高度。因此,当有图片网址时,高度为100.0,当图片网址为零时,高度为0.0 . 这是我在tableViewCell 课程中使用的代码:

func setConstraints(_height:CGFloat)
    self.commentImage.addConstraint(NSLayoutConstraint(item: self.commentImage,attribute: .height,relatedBy: .equal,toItem: self.commentImage,attribute: .width,multiplier: _height / 287.0,constant: 0))
    self.commentImage.updateConstraints()
    self.commentImage.layoutIfNeeded()


if let img = comment.image 
        let imgUrl = URL(string: img)
        self.commentImage.sd_setImage(with: imgUrl, placeholderImage: UIImage(named: "PlaceHolder Shop"))
        setConstraints(_height: 100.0)
    else 
        self.commentImage.image = nil
        setConstraints(_height: 0.0)
    

现在的问题是,当我滚动 tableview 时,一些没有图像 url 的行,得到 UIImageView 的高度为 100.0,这留下了一个空白区域,如果我滚动 tableView 非常快,有时行中的图像消失了。

我应该怎么做才能解决这个问题?我在这里缺少什么?

【问题讨论】:

在单元格中添加堆栈视图并将图像视图添加为子视图。根据 url 隐藏和显示图像视图。它会自动调整约束。 这很好。谢谢伙计。 【参考方案1】:

带有堆栈视图的CustomTableViewCell

class CustomTableViewCell: UITableViewCell 

  let titleLbl = UILabel()
  let stackView = UIStackView()
  let imgView = UIImageView()

    override func awakeFromNib() 
        super.awakeFromNib()
    

    override func setSelected(_ selected: Bool, animated: Bool) 
        super.setSelected(selected, animated: animated)
    
  override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    titleLbl.translatesAutoresizingMaskIntoConstraints = false
    addSubview(titleLbl)

    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.axis = .vertical
    stackView.spacing = 0
    stackView.alignment = .fill
    stackView.distribution = .fill
    addSubview(stackView)

    imgView.translatesAutoresizingMaskIntoConstraints = false
    let imgViewHeight = imgView.heightAnchor.constraint(equalToConstant: 100)
    imgViewHeight.priority = .defaultLow
    imgViewHeight.isActive = true
    imgView.addConstraint(imgViewHeight)

    stackView.addArrangedSubview(imgView)

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[titleLbl]|", options: [], metrics: nil, views: ["titleLbl":titleLbl,"stackView":stackView]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[titleLbl(30)][stackView]|", options: [.alignAllLeading,.alignAllTrailing], metrics: nil, views: ["titleLbl":titleLbl,"stackView":stackView]))
  

  required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")
  


带有自动高度tableView的ViewController

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 

  @IBOutlet var tableView: UITableView!

  override func viewDidLoad() 
    super.viewDidLoad()
    tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomCell")
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 130
  

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 15
  

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as! CustomTableViewCell
    cell.titleLbl.text = "Row \(indexPath.row)"
    // set cell.imgView.image
    cell.imgView.isHidden = cell.imageView?.image == nil
    return cell
  

【讨论】:

【参考方案2】:

UITableViewCells 被回收。您的 setConstraints 方法实际上并未设置约束;它再次添加一个新的约束。要正确执行此操作,您只需在 Interface builder 中设置约束即可。在尺寸检查器中找到高度约束并双击它以在文档大纲中选择它。选项从约束拖动到您的 tableViewCell 以创建一个名为 heightConstraint 的 IBOutlet。更改代码如下:

func setConstraints(_height:CGFloat)
    heightConstraint.constant = height
    commentImage.setNeedsLayout()

【讨论】:

以上是关于iOS 在 UITableViewCell 中以编程方式设置 UIImageView 约束在滚动 tableview 时变得混乱的主要内容,如果未能解决你的问题,请参考以下文章

如何在标准 UITableViewCell 中以编程方式自动布局右侧的自定义 UIButton。

我在自定义 UITableViewCell 中以编程方式设置布局约束时遇到问题

以编程方式为 UITableViewCell 设置 LayoutMargins - iOS 7 替代方案

在 Swift 中以编程方式突出显示 UITableViewCell

Swift 在 UITableViewCell 中以正确的方式使用 UISlider?

如何在swift3中以其他方法更新UITableviewcell标签?