在UITableView中添加底部单元格并滚动

3
我想在UITableView底部添加单元格,并滚动以使其完全可见(就像在Whatsapp中发送或接收消息时一样)。
我尝试过这样做: [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:[self.tableView numberOfRowsInSection:0]-1 inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 但是这会导致图形故障,表格闪烁并产生不良滚动效果,而不是平稳的滚动。
有什么帮助吗?

2
我不能确定地说,但WhatsApp可能会滚动到tableView(0,0)的顶部。这是一些消息应用程序使用的技巧,它们会旋转tableView,然后将每个单元格旋转180度。这给人以向下滚动的视觉效果,但编程视图却是向上滚动。 - Avi
1
将animated:YES更改为animated:NO。 - Subash
Subash的建议是有效的。你不能同时拥有两个呼叫动画。 - Dave
4个回答

2
我所做的是插入了一行,然后更改了tableView的内容插入。
-(IBOutlet)sendButton:(id)sender
{
    [array addObject:textView.text];
    [self addAnotherRow];
}
- (void)addAnotherRow {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:(array.count - 1) inSection:0];
        [self.messagesTableView beginUpdates];
        [self.messagesTableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        [self.messagesTableView endUpdates];
        [self updateContentInsetForTableView:self.messagesTableView animated:YES];

        // TODO: if the scroll offset was at the bottom it can be scrolled down (allow user to scroll up and not override them)

        [self.messagesTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

- (void)updateContentInsetForTableView:(UITableView *)tableView animated:(BOOL)animated {
    NSUInteger lastRow = [self tableView:tableView numberOfRowsInSection:0];
    NSLog(@"last row: %lu", (unsigned long)lastRow);
    NSLog(@"items count: %lu", (unsigned long)array.count);

    NSUInteger lastIndex = lastRow > 0 ? lastRow - 1 : 0;

    NSIndexPath *lastIndexPath = [NSIndexPath indexPathForItem:lastIndex inSection:0];
    CGRect lastCellFrame = [self.messagesTableView rectForRowAtIndexPath:lastIndexPath];

    // top inset = table view height - top position of last cell - last cell height
    CGFloat topInset = MAX(CGRectGetHeight(self.messagesTableView.frame) - lastCellFrame.origin.y - CGRectGetHeight(lastCellFrame), 0);

    // What about this way? (Did not work when tested)
    // CGFloat topInset = MAX(CGRectGetHeight(self.tableView.frame) - self.tableView.contentSize.height, 0);

    NSLog(@"top inset: %f", topInset);

    UIEdgeInsets contentInset = tableView.contentInset;
    contentInset.top = topInset;
    NSLog(@"inset: %f, %f : %f, %f", contentInset.top, contentInset.bottom, contentInset.left, contentInset.right);

    NSLog(@"table height: %f", CGRectGetHeight(self.messagesTableView.frame));

    UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
    [UIView animateWithDuration:animated ? 0.25 : 0.0 delay:0.0 options:options animations:^{
        tableView.contentInset = contentInset;

    } completion:^(BOOL finished) {
    }];
}

注意:要查看数组中的现有消息,您还需要包含这个。
- (void)viewDidLayoutSubviews {
    [self updateContentInsetForTableView:self.messagesTableView animated:NO];
}

0

添加项目的示例函数:

- (IBAction)addItem:(UIBarButtonItem *)sender {
  [self.items addObject:[NSString stringWithFormat:@"Item %lu", self.items.count + 1]];

  NSIndexPath *indexPathToInsert = [NSIndexPath indexPathForRow:self.items.count - 1 inSection:0];
  [self.tableView insertRowsAtIndexPaths:@[indexPathToInsert] withRowAnimation:UITableViewRowAnimationAutomatic];
  [self.tableView scrollToRowAtIndexPath:indexPathToInsert atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

对我来说,这样的动画看起来非常完美!


我试过了,但整个表视图在闪烁时滚动...不管怎样,谢谢回复。 - facumedica

0

使插入动画化,并在 endUpdates 后滚动到底部而不进行动画。这对我有用。

Swift

self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(newIndexPaths, withRowAnimation: UITableViewRowAnimation.Top)
self.tableView.endUpdates()
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.tableDataCount-1, inSection: 0), atScrollPosition: .Bottom, animated: false)

0

好的,我的做法是使用[self.tableView scrollToRowAtIndexPath...,但是通过0.1秒的NSTimer来调用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接