I have a custom cell 'CustomCell' that I wish to compose based on a custom data element. I am trying to add subviews to CustomCell but for those subviews loaded from a xib ( https://stackoverflow.com/a/26326006/3546621 ), I can't figure out how to layout them into the cell's contentView; ie programmatically setting their frame nor adding constraints seem to work. ( CustomCell has no xib attached, every subviews is loaded programmatically. Some of these subview are loaded from xib.)
For example, here is my custom cell. It has two subviews, a yellowView initialized with UIView(frame: CGRect()) and right below a blueView initialized with UIView.fromNib.
This is BlueView.xib
I am not succeeding at placing blueView below yellowView, instead I have the blueView being stacked on top of the yellowView:
class CustomCell: UITableViewCell {
let yellowView: UIView = UIView()
let blueViewFromXib: BlueView = UIView.fromNib()
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
fun configureForData(custom: Custom){
yellowView.backgroundColor = UIColor.yellowColor()
yellowView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(yellowView)
blueView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(blueView)
layoutIfNeeded()
}
override func layoutSubviews() {
super.layoutSubviews()
let height = NSLayoutConstraint(item: contentView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 80)
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.addConstraint(height)
yellowView.frame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: 40)
// I want to add the blueView at the bottom of the yellowView
// Option 1: not working
blueView.frame = CGRect(x: 0, y: 40, width: contentView.frame.width, height: 40)
// Option 2: not working
let top = NSLayoutConstraint(item: blueView, attribute: .Top, relatedBy: .Equal, toItem: contentView, attribute: .Top, multiplier: 1, constant: 40)
let bottom = NSLayoutConstraint(item: blueView, attribute: .Bottom, relatedBy: .Equal, toItem: contentView, attribute: .Bottom, multiplier: 1, constant: 0)
let leading = NSLayoutConstraint(item: blueView, attribute: .Leading, relatedBy: .Equal, toItem: contentView, attribute: .Leading, multiplier: 1, constant: 0)
let trailing = NSLayoutConstraint(item: blueView, attribute: .Trailing, relatedBy: .Equal, toItem: contentView, attribute: .Trailing, multiplier: 1, constant: 0)
contentView.addConstraints([top, bottom, leading, trailing])
}
}
class BlueView: UIView {
// the project includes a BlueView.xib which is simply a UIView whose background color is blue
}
View Controller
override func viewDidLoad(){
super.viewDidLoad()
tableView.delegate = self
tableView.datasource = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 80
tableView.registerClass(CustomCell.self, forCellReuseIdentifier: "CustomCell")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let custom = customs[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomCell
cell.configureForData(custom)
return cell
}
A couple things to be aware of
In layoutSubviews you shouldn't be adding/removing constraints that don't change. If you set the constraints, the default implementation ( super.layoutSubviews()
) will adjust the size/layout based on the constraints.
If you set constraints, they override any frames that were set.
blueView.frame = UIView(frame: CGRect(x: 0, y: 40, width: contentView.frame.width, height: 40))
shouldn't even compile. You're setting blueView's frame (a CGRect) to a new instance of UIView.
Regardless, it appears you're using layoutConstraints for blueView, and manually setting the frame for yellowView. I'm guessing if you use one of these you will be able to work out what's going on.
To simplify things, try setting your subViews to optionals:
let yellowView: UIView?
let blueViewFromXib: BlueView?
Then comment out layoutSubviews, and use this:
func configureForData(custom: Custom){
if yellowView == nil {
yellowView = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.width, height: 40))
yellowView?.backgroundColor = UIColor.yellowColor()
self.addSubview(yellowView)
}
if blueView == nil {
blueView = BlueView.fromNib()
blueView?.frame = CGRect(x: 0, y: 40, width: self.frame.width, height: 40)
self.addSubview(blueView)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.