Home > Back-end >  How to calculate an aspect ratio of cell to different mobile size?
How to calculate an aspect ratio of cell to different mobile size?

Time:02-02

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:

enter image description here enter image description here


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 is 369 (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)
 }
  • Related