I have a table view properly configured to have dynamic row heights based on Ray Wenderlich's guide found here:
I set up the constraints to have a clear line of constraints from the top to the bottom of the cell. I also set up content hugging and content compression resistance priorities and estimated row height.
This is the code I use to setup the table view:
func configureTableView() {
// its called on viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100.0
}
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
for i in 1...20 {
messages.append([
"title": "foo \(i)",
"message": "bla \(i)\nbla\nbla"
])
}
// this is because the actual row heights are not available until the next layout cycle or something like that
dispatch_async(dispatch_get_main_queue(), {self.scrollToBottom(false)})
}
func scrollToBottom(animated:Bool) {
let indexPath = NSIndexPath(forRow: self.messages.count-1, inSection: 0)
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
}
And this is how I add new rows:
@IBAction func addMore(sender:UIBarButtonItem) {
let message = [
"title": "haiooo",
"message": "silver"]
messages.append(message)
let indexPath = NSIndexPath(forRow: messages.count-1, inSection: 0)
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Bottom)
scrollToBottom(true)
}
The setup with the default rows are fine. It add the rows and scrolls to the bottom as expected.
But when I add new rows after that, the scrolling seems to start above the last cell. As I add more cells, the offset seems to increase.
Here is a gif showing it happening: Imgur
It's certainly related to the scroll animation (not the insertRow animation) because it scrolls properly when the animation is turned off.
Changing the estimatedRowHeight
makes difference on the scrolling offset, but I couldn't find a value that fixed it.
I also tried delaying up the scroll using dispatch_async
but it didn't change anything.
Do you guys have any ideas?
Wow, that was a fun challenge. Thanks for posting the test project.
So it seems that after adding the new row there's something off with where the table view thinks it's scrolled to. Seems to me to be a bug in UIKit. So to work around that, I added some code to 'reset' the table view before applying the animation.
Here's what I ended up with:
@IBAction func addMore(sender:UIBarButtonItem) {
let message = [
"title": "haiooo",
"message": "silver"]
messages.append(message)
tableView.reloadData()
// To get the animation working as expected, we need to 'reset' the table
// view's current offset. Otherwise it gets confused when it starts the animation.
let oldLastCellIndexPath = NSIndexPath(forRow: messages.count-2, inSection: 0)
self.tableView.scrollToRowAtIndexPath(oldLastCellIndexPath, atScrollPosition: .Bottom, animated: false)
// Animate on the next pass through the runloop.
dispatch_async(dispatch_get_main_queue(), {
self.scrollToBottom(true)
})
}
I couldn't get it to work with insertRowsAtIndexPaths(_:withRowAnimation:)
, but reloadData()
worked fine. Then you need the same delay again before animating to the new last row.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With