scrollToRowAtIndexPath:atScrollPosition导致表格视图“跳转"到表中. [英] scrollToRowAtIndexPath:atScrollPosition causing table view to "jump"

查看:76
本文介绍了scrollToRowAtIndexPath:atScrollPosition导致表格视图“跳转"到表中.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序具有聊天功能,并且正在输入新消息,如下所示:

My app has chat functionality and I'm feeding in new messages like this:

[self.tableView beginUpdates];
[messages addObject:msg];
[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:messages.count - 1 inSection:1]] withRowAnimation:UITableViewRowAnimationBottom];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:messages.count - 1 inSection:1] atScrollPosition:UITableViewScrollPositionBottom animated:YES];

但是,当我添加新消息时(发送和接收,结果都相同),我的表视图会奇怪地跳转":

However, my table view "jumps" weirdly when I'm adding a new message (either sending and receiving, result is the same in both):

为什么我会收到这个奇怪的跳转"?

Why am I getting this weird "jump"?

推荐答案

好的,我知道了.正如您所说,问题与自动调整单元格大小有关.我使用了两个技巧来使事情正常工作(我的代码在Swift中,但是应该很容易转换回ObjC):

OK, I figured it out. As you say, the problem has to do with auto-sizing cells. I used two tricks to make things work (my code is in Swift, but it should be easy to translate back to ObjC):

1)等待表格动画完成,然后再采取进一步的措施.这可以通过将更新表的代码包含在CATransaction.begin()CATransaction.commit()之间的块中来完成.我在CATransaction上设置了完成代码块-该代码将在动画完成后运行.

1) Wait for the table animation to finish before taking further action. This can be done by enclosing the code that updates the table within a block between CATransaction.begin() and CATransaction.commit(). I set the completion block on CATransaction -- that code will run after the animation is finished.

2)在滚动到底部之前,强制表格视图呈现单元格.我通过少量增加表的contentOffset来做到这一点.这会使新插入的单元格出队,并计算其高度.滚动完成后(我等待使用上面的方法(1)完成滚动),最后调用tableView.scrollToRowAtIndexPath.

2) Force the table view to render the cell before scrolling to the bottom. I do it by increasing the table's contentOffset by a small amount. That causes the newly inserted cell to get dequeued, and its height gets calculated. Once that scroll is done (I wait for it to finish using the method (1) above), I finally call tableView.scrollToRowAtIndexPath.

代码如下:

override func viewDidLoad() {
    super.viewDidLoad()

    // Use auto-sizing for rows        
    tableView.estimatedRowHeight = 40
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.dataSource = self
}

func chatManager(chatManager: ChatManager, didAddMessage message: ChatMessage) {
    messages.append(message)

    let indexPathToInsert = NSIndexPath(forRow: messages.count-1, inSection: 0)

    CATransaction.begin()
    CATransaction.setCompletionBlock({ () -> Void in
        // This block runs after the animations between CATransaction.begin
        // and CATransaction.commit are finished.
        self.scrollToLastMessage()
    })

    tableView.beginUpdates()
    tableView.insertRowsAtIndexPaths([indexPathToInsert], withRowAnimation: .Bottom)
    tableView.endUpdates()

    CATransaction.commit()
}

func scrollToLastMessage() {
    let bottomRow = tableView.numberOfRowsInSection(0) - 1

    let bottomMessageIndex = NSIndexPath(forRow: bottomRow, inSection: 0)

    guard messages.count > 0
        else { return }

    CATransaction.begin()
    CATransaction.setCompletionBlock({ () -> Void in

        // Now we can scroll to the last row!
        self.tableView.scrollToRowAtIndexPath(bottomMessageIndex, atScrollPosition: .Bottom, animated: true)
    })

    // scroll down by 1 point: this causes the newly added cell to be dequeued and rendered.
    let contentOffset = tableView.contentOffset.y
    let newContentOffset = CGPointMake(0, contentOffset + 1)
    tableView.setContentOffset(newContentOffset, animated: true)

    CATransaction.commit()
}

这篇关于scrollToRowAtIndexPath:atScrollPosition导致表格视图“跳转"到表中.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆