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
Swift 3 - Passing Data Between a View Controller and After That to Another 2
Swiftui Card Flip Animation with Two Views, One of Which Is Embedded Within a Stack
Swift 3 Filter Array of Dictionaries by String Value of Key in Dictionary
iOS Swift Avplayer Inside Uiview How to Make It Work
Swift: Triggering Tableviewcell to Lead to a Link in a Uiwebview in Another Viewcontroller
How to Change Uinavigationbar Per View Controller
How to Open a Local PDF File Using a Swiftui Button
Google Cloud Messaging Bridging Header Import Fails
If Let Doesn't Unwrap Optional Value for Mkannotation's Title Property
iOS Development App Startup Crash
Dyld: Symbol Not Found: _Tmpdcss12Anygenerator
How to Make Designable Textfield Code Class in Swift
Scene Kit Memory Management Using Swift
Changing Constraint When Keyboard Appears - Swift
Could Not Cast Value of Type 'Nsnull' (0X10Aa1B600) to 'Nsstring' (0X10B4Dab48)