Uitableviewcell Custom Class - Reload Cell Height After Change in Subview Height Constraint

UITableViewCell custom class - Reload cell height after change in subview height constraint

Add the following method to the viewController with the tableView to refresh the table when a cell is expanded:

func refreshTableAfterCellExpansion() {
self.tableView.beginUpdates()
self.tableView.setNeedsDisplay()
self.tableView.endUpdates()
}

Call the method after the constraints have been updated. If the button manipulates the constraints inside the cell, you will need to notify the viewController about the change so that you can call the method. Either use a delegate pattern (or pass directly a tableView reference to each expandable cell - just remember to store it as weak variable), or post a notification using NotificationCenter.default.

Custom TableViewCell with Subview whose height changes

The best approach is to use Auto Layout and self-sizing cells. Setup constraints in storyboard for your custom cell.

You will not need to reload the tableView. Each cell will automatically adjust its height, based on how much vertical space its subview takes.

For more information, see the detailed walkthrough by smileyborg in his answer to Using Auto Layout in UITableView for dynamic cell layouts & variable row heights.

Change Height Constraint for View wrapped in UITableViewCell

You don't wanna do that. And that won't work, as far as I know. You need to setup your constraints, either in your cell's init. Or in your cellForRow function.

So in my codes below, I modified yours, and I add a property (height constraint) of your NestedView inside your TestCell cell. And I update that height inside the cellForRow.

Edit: if you want to toggle a cell height, of course you do it the same way, you just need to reload the rows/sections or whole data of your tableView.

ViewController.swift

import UIKit
import SnapKit

class ViewController: UIViewController {

let tableView = UITableView.init(frame: .zero)

override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.edges.equalTo(self.view)
}

tableView.register(UITableViewCell.self, forCellReuseIdentifier: "X")
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 100
tableView.delegate = self
tableView.dataSource = self
}

}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if indexPath.row == 5 {
let c = TestCell.init(style: .default, reuseIdentifier: nil)
c.constraint_HeightOfNestedView?.update(offset: 100.0)
return c

}

let c = tableView.dequeueReusableCell(withIdentifier: "X")
c?.backgroundColor = .orange
return c!
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
}

TestCell.swift

import SnapKit

class TestCell: UITableViewCell {
var constraint_HeightOfNestedView: Constraint?
let nestedView = NestedView()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)

addSubview(nestedView)
nestedView.snp.makeConstraints { make in
make.edges.equalTo(self)
self.constraint_HeightOfNestedView = make.height.equalTo(20.0).priority(999).constraint
}
backgroundColor = .blue

}

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

NestedView.swift

import UIKit

class NestedView: UIView {

override init(frame: CGRect) {
super.init(frame: frame)

backgroundColor = .yellow
}

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

UITableView Custom Cell Height Not Working

You haven't implemented the UITableViewDelegate

In your setupTable() add the line

tableView.delegate = self

Then change your extension from

extension ViewController: UITableViewDataSource {

to extension ViewController: UITableViewDataSource, UITableViewDelegate {

Different UITableViewCell subviews layout after tapping a cell

I'd have different cells and reload them as the cells are clicked.

class TableViewController: UITableViewController {

var largeRow: IndexPath?

var data: [Int] = [0, 1, 2, 3, 4, 5, 6, 7]

override func viewDidLoad() {
super.viewDidLoad()
}
}

extension TableViewController {

override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath == largeRow {
return makeLargeCell(at: indexPath)
} else {
return makeNormalCell(at: indexPath)
}
}
}

extension TableViewController {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)

if let largeRow = largeRow {
if largeRow == indexPath {
self.largeRow = nil
tableView.reloadRows(at: [indexPath], with: .fade)
} else {
self.largeRow = indexPath
tableView.reloadRows(at: [largeRow, indexPath], with: .fade)
}
} else {
self.largeRow = indexPath
tableView.reloadRows(at: [indexPath], with: .fade)
}
}
}

Increasing a custom view's height in a table view row (and as a result the row's one, too) programmatically

You've done everything right, and your constraints are correct, but the table view has not heard about the fact that they have changed. You need to reload the table view (or at least this row).

The best way to do that, by the way, is by performing an empty batch update, because that will cause the change in constraints to be animated, which is a very nice look.

EDIT: I say "your constraints are correct", but a comment that you later added suggests that this is not true. It sounds like you are trying to "mix and match" fixed layout with autolayout: your custom view uses autolayout, but its subviews do not. Don't do that.

Instead of changing the height constraint of your custom view manually, you should be using constraints internally for all the subviews so that their constraints size the custom view from the inside out — exactly in the same way that the cell itself works. Either that, or you should turn off autoresizing of the cell and implement heightForRowAt to dictate the entire cell height manually.

How to update data and view of my customized cell subview?

At first, before updating cell, you should remove from superview early initiated testItemView, because at updateCells method you are create new instance of testItemView and add for new created view constraints again.


I think this code should work for you, replace you updateCell method:

func updateCell(infos: [Info]) {
testContainView.removeFromSuperView
testContainView = createItemView(infos: infos)

contentView.addSubview(testItemView!)

testItemView?.snp.makeConstraints { (make) in
make.left.equalTo(13)
make.top.equalTo(10)
make.right.equalTo(-13)
make.height.equalTo(195)
make.bottom.equalTo(-10)
}
}

UITableView dynamic cell heights only correct after some scrolling

I don't know this is clearly documented or not, but adding [cell layoutIfNeeded] before returning cell solves your problem.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
NSUInteger n1 = firstLabelWordCount[indexPath.row];
NSUInteger n2 = secondLabelWordCount[indexPath.row];
[cell setNumberOfWordsForFirstLabel:n1 secondLabel:n2];

[cell layoutIfNeeded]; // <- added

return cell;
}


Related Topics



Leave a reply



Submit