我现在在聊天屏幕上工作(UITableView +输入TextField)。
当我滚动到顶部时,我希望我的UITableView
重新加载更多聊天消息保持当前滚动位置(如果我更多地加载20条消息,我仍然会看到第21条消息。) KakaoTalk 和行应用正在执行此操作。在那个应用程序中,我可以无限滚动,因为滚动位置停留。(我的意思是我仍然看到相同的聊天消息)
我正在检查tableView:willDisplayCell:forRowAtIndexPath:
中的行索引,所以当索引为0时我会获取更多的聊天消息。我完成了从DB获取更多消息的逻辑,但我没有完成抛光UI。
这是代码。
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 && !isTableViewLoading {
if photo.chatMessages.count != chatMessages.count {
var loadingChatItems: Array<ChatMessage>
let start = photo.chatMessages.count - chatMessages.count - Metric.ChatMessageFetchAmount
if start > 0 {
loadingChatItems = Database.loadChatMessages(photoId, startIndex: start, amount: Metric.ChatMessageFetchAmount)
} else {
loadingChatItems = Database.loadChatMessages(photoId, startIndex: 0, amount: Metric.ChatMessageFetchAmount + start)
}
chatMessages = loadingChatItems + chatMessages
isTableViewLoading = true
var indexPaths = Array<NSIndexPath>()
for row in 0..<loadingChatItems.count {
let indexPath = NSIndexPath(forRow: row, inSection: 0)
indexPaths.append(indexPath)
}
tableView.scrollEnabled = false
tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.None)
}
} else {
isTableViewLoading = false
tableView.scrollEnabled = true
}
}
有什么建议吗?
答案 0 :(得分:3)
Swift 3
这篇文章有点陈旧,但这里有一个解决方案:
1)在scrollViewDidScroll,
中滚动到顶部时检测到2)加载新消息
3)保存contentSize,重新加载tableView
4)将tableView的contentOffset.y设置为(newContentSizeHeight - oldContentSizeHeight),这正好是当前点
这里是代码:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == tableView {
if tableView.contentOffset.y < 50 {
loadMessages()
let oldContentSizeHeight = tableView.contentSize.height
tableView.reloadData()
let newContentSizeHeight = tableView.contentSize.height
tableView.contentOffset = CGPoint(x:tableView.contentOffset.x,y:newContentSizeHeight - oldContentSizeHeight)
}
}
}
答案 1 :(得分:0)
在viewDidLoad
:
self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
然后添加功能:
func refresh(refreshControl: UIRefreshControl) {
//your code here
refreshControl.endRefreshing()
}
这将允许用户向上滚动以刷新UITableView。
答案 2 :(得分:0)
我已经实现了另一种解决方案,它使用委托中的滚动侦听器以及异步服务的响应。
因此,它会在没有动画的情况下滚动到开始加载更多消息的位置,因为消息已附加到我的数组中(这几乎不会影响过渡)。
我之所以决定这样做,是因为第一个解决方案有一个问题,那就是当您自动设置行高时,新的内容高度将不准确。
这是我的代码。
- (void) scrollViewDidScroll:(UIScrollView*)scrollView {
if (!topReached && scrollView == self.table) {
if (!isLoadingTop && self.table.contentOffset.y < 40) {
isLoadingTop = YES;
[self loadChat];
}
}
}
// method used by the response of the async service
- (void)fillMessages: (NSArray*) messageArray {
if ([messageArray count] == 0) {
topReached = YES;
} else {
if ([messageArray count] < limit) {
topReached = YES;
}
for (int i=0; i<messageArray.count; i++) {
NSDictionary* chat = [messageArray objectAtIndex:i];
[messages insertObject:[[MessageModel alloc] initWithDictionary:chat] atIndex:i];
}
[table reloadData];
if (!isLoadingTop)
[self scrollToBottom];
else {
isLoadingTop = NO;
[self.table
scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[messageArray count] inSection:0]
atScrollPosition:UITableViewScrollPositionTop animated:false];
}
offset += limit;
}
}
作为辅助信息,我想在视图控制器中阻止对异步服务消耗的访问,因此在同一视图中只能调用一次服务。