I need a help! How can I calculate the aspect ratio of view which locates in tableView cell, this view should display for different devices (17 : 10) in this aspect ratio. I have a table which contains a certain number of cells. I set an arbitrary table's cell length of 226.0. This is done to show an arbitrary distance of 24 points between cells. (No-Storyboard)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 226.0
}
Inside the cell, I have a view that matches a height of (17:10). I use a SnapKit for constraints.
cellView.snp.makeConstraints { make in
make.top.equalTo(self.contentView.snp.top)
make.leading.equalTo(self.contentView.snp.leading)
make.trailing.equalTo(self.contentView.snp.trailing
make.height.equalTo(self.contentView.snp.width).multipliedBy(10.0 / 17.0)
}
For test I am using iPhone SE (3rd generation), after running the application, the aspect ratio only works for this model which has a distance of 24 points between cells. If you run other simulator models, such as iphone 14 pro max, the cells stick together. How can I calculate so that for different models the distance always remains 24 points between cells?
Edit
SE 3rd Gen Simulator result
As you can see in the screenshot, this simulator corresponds to the aspect ratio of 17:10 and plus there is a distance between other cells of 24 points. But if you run a simulator of a larger model, then the cells stick together.
CodePudding user response:
You want to allow the cells to set their own height, so...
Get rid of this completely:
//func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return 226.0
//}
Configure your cell class like this:
class AspectCell: UITableViewCell {
let cellView = UIView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
cellView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(cellView)
cellView.snp.makeConstraints { make in
// use Priority of Required-1 to avoid autolayout complaints
make.top.bottom.equalTo(self.contentView).inset(12.0).priority(.init(999.0))
make.leading.trailing.equalTo(self.contentView).inset(12.0)
make.height.equalTo(self.contentView.snp.width).multipliedBy(10.0 / 17.0)
}
cellView.backgroundColor = .systemRed
cellView.layer.cornerRadius = 12
}
}
and here's a basic table view controller to see the results:
class AspectTableViewController: UITableViewController {
let colors: [UIColor] = [
.systemRed, .systemGreen, .systemBlue,
.systemYellow, .green, .blue,
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.separatorStyle = .none
tableView.register(AspectCell.self, forCellReuseIdentifier: "aspectCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "aspectCell", for: indexPath) as! AspectCell
c.cellView.backgroundColor = colors[indexPath.row % colors.count]
return c
}
}
Output:
Edit - to clarify constraint priority...
A very common situation when using dynamic sizing constraints in cells (and other views) is we end up with a not-quite-valid value.
For example, running this on aniPhone 14 Pro, the cellView
with 12-points on each side:
- actual width of the cell is
393
- actual width of
cellView
subview is369
(393 - 24) - 369.0 x 10.0 / 17.0 = 217.05882352941177
Auto-layout will print warnings to the debug console because it cannot set a Height of 217.05882352941177
... it will use 217
.
By giving the Bottom constraint a Priority of less-than-required, we're telling auto-layout that we're okay if it uses 217
(i.e. it is not required).
This is a better makeConstraints block (we don't need to lower the priority on the top constraint). And, the code above used the contentView
width instead of the cellView
width, so it was not quite 17:10 aspect ratio:
cellView.snp.makeConstraints { make in
// 12-points on each side
make.leading.trailing.equalTo(self.contentView).inset(12.0)
// 12-points from the top
make.top.equalTo(self.contentView).inset(12.0)
// proportional height (17:10)
make.height.equalTo(cellView.snp.width).multipliedBy(10.0 / 17.0)
// use Priority of Required-1 to avoid autolayout complaints
make.bottom.equalTo(self.contentView).inset(12.0).priority(.init(999.0))
}
CodePudding user response:
Try this solution you no need to provide height as you have already provide height in heightForRowAt func which is 226, so it will remain same in all iPhones screen
From this
cellView.snp.makeConstraints { make in
make.top.equalTo(self.contentView.snp.top)
make.leading.equalTo(self.contentView.snp.leading)
make.trailing.equalTo(self.contentView.snp.trailing
make.height.equalTo(self.contentView.snp.width).multipliedBy(10.0 / 17.0)
}
To this
let view = UIView()
view.backgroundColor = .systemPink
contentView.addSubview(view)
view.snp.makeConstraints { make in
make.left.equalTo(15.adjusted)
make.right.equalTo(contentView.snp.right).offset(-15)
make.bottom.equalTo(contentView.snp.bottom).offset(-12)
make.top.equalTo(12.adjusted)
}