使用 uilabel 和 uiimageview 以编程方式为 uitableviewcell 设置约束

问题描述 投票:0回答:2

我正在尝试使用自定义 UITableViewCell 构建我的 tableview,但在 coinstraints 中遇到了一些问题。以下是我的自定义 UITablviewCell 类:

class MovieCell: UITableViewCell {
static let identifier = "MovieCell"
let cellMargin = 15.0

private lazy var containerView: UIView = {
   let view = UIView()
    view.backgroundColor = .lightGray
    view.layer.cornerRadius = 5
    view.translatesAutoresizingMaskIntoConstraints = false
    view.clipsToBounds = true
    return view
}()

private let movieNameLabel: UILabel = {
   let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont.movieAppBoldFont(size: 15)
    label.numberOfLines = 0
    return label
}()

private let movieImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true
    return imageView
}()

var movieCellViewModel : MoviewCellViewModel = MoviewCellViewModel(image: nil, name: "") {
    didSet {
        movieNameLabel.text = movieCellViewModel.name
    }
}

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0)
    layoutSubView()
}

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

private func layoutSubView() {
    addSubview(containerView)
    containerView.addSubview(movieNameLabel)
    containerView.addSubview(movieImageView)
    
    let marginGuide = containerView.layoutMarginsGuide
    
    NSLayoutConstraint.activate([
        containerView.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor),
        containerView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),
        containerView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor),
        containerView.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor, constant: -cellMargin),
        
        movieImageView.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor, constant: 5),
        movieImageView.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 5),
        movieImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5),
        movieImageView.widthAnchor.constraint(equalToConstant: 50),
        movieImageView.heightAnchor.constraint(equalToConstant: 50),

        movieNameLabel.leadingAnchor.constraint(equalTo: marginGuide.trailingAnchor, constant: 5),
        movieNameLabel.trailingAnchor.constraint(equalTo: marginGuide.trailingAnchor, constant: -5),
        movieNameLabel.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 5),
        movieNameLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor, constant: -5)
    ])
}

}

我用上面的代码得到以下结果:

我正在尝试创建一个 UIView 并向其添加内容。我添加它是因为我想在 tableview 中显示一些空白作为分隔符。

ios swift uitableview nslayoutconstraint
2个回答
1
投票

情侣问题...

你在

layoutSubView()
的第一行是:

addSubview(containerView)

需要在哪里:

contentView.addSubview(containerView)

其次,你有

movieImageView
约束到
contentView

movieImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5),

应该限制在

marginGuide

movieImageView.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor, constant: -5),

第三,你有

movieNameLabel.leadingAnchor
约束到
marginGuide.trailingAnchor

movieNameLabel.leadingAnchor.constraint(equalTo: marginGuide.trailingAnchor, constant: 5),

应该限制在

movieImageView.trailingAnchor

movieNameLabel.leadingAnchor.constraint(equalTo: movieImageView.trailingAnchor, constant: 5),

进行这些更改会给你这个(我将图像视图背景设置为蓝色,并将标签背景设置为青色):

但是,当您运行该应用程序时,您会看到很多Unable to simultaneously satisfy constraints.消息。这在单元格中使用带有子视图的子视图时很常见。

为了摆脱自动布局投诉,我们可以给

containerView
底部锚点一个低于要求的优先级:

let bottomC = containerView.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor, constant: -cellMargin)
bottomC.priority = .required - 1

然后在你的约束块中激活它:

//containerView.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor, constant: -cellMargin),
bottomC,

这是您完成的

MovieCell
课程,其中包含这些更改:

class MovieCell: UITableViewCell {
    static let identifier = "MovieCell"
    let cellMargin = 15.0
    
    private lazy var containerView: UIView = {
        let view = UIView()
        view.backgroundColor = .lightGray
        view.layer.cornerRadius = 5
        view.translatesAutoresizingMaskIntoConstraints = false
        view.clipsToBounds = true
        return view
    }()
    
    private let movieNameLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = .systemFont(ofSize: 15, weight: .bold) // UIFont.movieAppBoldFont(size: 15)
        label.numberOfLines = 0
        return label
    }()
    
    private let movieImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        return imageView
    }()
    
    var movieCellViewModel : MoviewCellViewModel = MoviewCellViewModel(image: nil, name: "") {
        didSet {
            movieNameLabel.text = movieCellViewModel.name
        }
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0)
        layoutSubView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func layoutSubView() {
        contentView.addSubview(containerView)
        containerView.addSubview(movieNameLabel)
        containerView.addSubview(movieImageView)
        
        let marginGuide = containerView.layoutMarginsGuide
    
        let bottomC = containerView.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor, constant: -cellMargin)
        bottomC.priority = .required - 1

        NSLayoutConstraint.activate([
            containerView.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor),
            containerView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),
            containerView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor),
//          containerView.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor, constant: -cellMargin),
            bottomC,
            
            movieImageView.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor, constant: 5),
            movieImageView.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 5),
//          movieImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5),
            movieImageView.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor, constant: -5),
            movieImageView.widthAnchor.constraint(equalToConstant: 50),
            movieImageView.heightAnchor.constraint(equalToConstant: 50),
            
//          movieNameLabel.leadingAnchor.constraint(equalTo: marginGuide.trailingAnchor, constant: 5),
            movieNameLabel.leadingAnchor.constraint(equalTo: movieImageView.trailingAnchor, constant: 5),
            movieNameLabel.trailingAnchor.constraint(equalTo: marginGuide.trailingAnchor, constant: -5),
            movieNameLabel.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 5),
            movieNameLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor, constant: -5)
        ])

        // during dev, so we can easily see the frames
        movieImageView.backgroundColor = .systemBlue
        movieNameLabel.backgroundColor = .cyan
    }
}

-1
投票
  private var lbl: UILabel = {
    let lbl = UILabel()
    lbl.textColor = .black
    lbl.translatesAutoresizingMaskIntoConstraints = false
    lbl.numberOfLines = 1
    return lbl
  }()
  
  private var imgView: UIImageView = {
    let imgView = UIImageView()
    imgView.translatesAutoresizingMaskIntoConstraints = false
    imgView.contentMode = .scaleAspectFit
    return imgView
  }()
  
  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    configure()
  }
  
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  private func configure() {
    selectionStyle = .none
    self.addSubview(imgView)
    self.addSubview(lbl)
    
    NSLayoutConstraint.activate([
      imgView.widthAnchor.constraint(equalToConstant: 80),
      imgView.heightAnchor.constraint(equalToConstant: 80),
      imgView.topAnchor.constraint(equalTo: topAnchor, constant: 10),
      // using lessThanOrEqualTo is the key 
      imgView.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -10),
      imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
      
      lbl.centerYAnchor.constraint(equalTo: imgView.centerYAnchor),
      lbl.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 10),
      lbl.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20)
    ])
  }
© www.soinside.com 2019 - 2024. All rights reserved.