在自动调整TextView大小时输入文本时,UITableView会闪烁/断断续续

时间:2014-12-13 15:51:46

标签: ios uitableview

目前,我有一个UITableView,其中包含调整大小UITextView。该单元格正在使用beginUpdates / endUpdates自动调整大小,但是当它执行此操作时,表格视图会断断续续(请参阅下面的gif)。

最终结果是UITableViewCell,其中包含一个基于其内容调整大小的文本视图。以下是自定义UITableViewCell类中的代码,该代码会导致UITableView自行更新。

- (void)textViewDidChange:(UITextView *)textView {
    // This is a category on UITableViewCell to get the [self superView] as the UITableView
    UITableView *tableView = [self tableView];
    if (tableView){
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

以下是我已经尝试过的事情:

获取当前contentOffset并在endUpdates之后重置,但没有工作 在更新之前禁用UITableView上的滚动,然后启用 我尝试始终从NO返回- (BOOL)textViewShouldEndEditing:(UITextView *)textView 我的UITableView单元格高度使用UITableViewAutomaticDimension。欢迎任何其他想法或想法。

以下是一个示例:

Table View Stutter

我不打算使用任何库,所以请不要提出任何建议。

由于

编辑:解决方案

在此处找到:I do not want animation in the begin updates, end updates block for uitableview?

感谢@JeffBowen获得了一个很棒的发现(虽然hacky它是可行的并且允许我仍然实现支持iOS 7的UITableViewDelegate方法)。在执行更新之前关闭动画,然后在更新后启用以防止UITableView出现口吃。

[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];

如果您不需要使用Delegate方法,并且只想要iOS 8+的解决方案,那么请使用@ Massmaker的答案。

4 个答案:

答案 0 :(得分:4)

只需在调用beginUpdates之前停用动画,并在致电endUpdates后重新启用动画。

[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];

绝对是一个黑客但现在有效。感谢我的朋友Beau,他指的是this

答案 1 :(得分:1)

我的解决方案(适用于iOS 8)首先在我的viewController viewDidLoad

中设置
self.tableView.rowHeight = UITableViewAutomaticDimension;
// this line is needed to cell`s textview change cause resize the tableview`s cell
self.tableView.estimatedRowHeight = 50.0;

然后,结合这篇文章solution in Swift和一些肮脏的想法 我在我的单元格中设置了一个名为

的属性
@property (nonatomic, strong) UITableView *hostTableView;

并在cell-s -(void) textViewDidChange:(UITextView *)textView

 CGFloat currentTextViewHeight = _textContainer.bounds.size.height;
CGFloat toConstant = ceilf([_textContainer sizeThatFits:CGSizeMake(_textContainer.frame.size.width, FLT_MAX)].height);
if (toConstant  >  currentTextViewHeight)
{
    [_hostTableView beginUpdates];
    [_hostTableView endUpdates];
}

然后在viewController中

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

textCell.hostTableView = self.tableView;

after height change

答案 2 :(得分:0)

我找不到实现目标的方法,因为: 当您触发[tableView endUpdates]时,表重新计算contentSize并重新设置它。这会导致将contentOffset重置为默认值。

这是从UIScrollView继承的行为,我试图通过以下方式避免它:

  • 对UITableView进行子类化并覆盖setContentOffset:setContentOffset:animated函数。但是当表格视图更改contentSize时,他们不会调用。
  • 在内容大小更新后,对UITableView进行子类化,覆盖setContentSize:函数并将contentOffset设置为旧值,但它对我不起作用
  • 使用KVO,并在重置后立即为contentOffset设置旧值,但无论如何我有这个动画问题
  • 将scrollEnabled设置为NO并将scrollToTop设置为NO,但它也没有帮助

如果有人为此问题找到解决方案欢迎。 也许可能的解决方案 - 禁用自动布局:iOS: setContentSize is causing my entire UIScrollView frame to jump

更新:我找到解决方案:直接更改单元格高度,内容大小和内容偏移量: 这适用于我(表格视图是单元格的UITextView的委托)

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat textHeight = [textView sizeThatFits:CGSizeMake(self.width, MAXFLOAT)].height;
    if (self.previousTextHeight != textHeight && self.previousTextHeight > 0) {
        CGFloat difference = textHeight - self.previousTextHeight;
        CGRect cellFrame = self.editedCell.frame;
        cellFrame.size.height += difference;
        self.editedCell.frame = cellFrame;
        self.contentSize = CGSizeMake(self.contentSize.width, self.contentSize.height + difference);
        self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + difference);
    }
    self.editedNote.comments = textView.text;
}

答案 3 :(得分:0)

在Textview值更改委托中,使用此代码调整特定单元格的大小,而不会出现任何闪烁。 但在此之前,请确保已使用动态tableview单元格高度。

UIView.setAnimationsEnabled(false)
DispatchQueue.main.async {
   self.tableView.beginUpdates()
   self.tableView.endUpdates()
   self.tableView.layer.removeAllAnimations()
}
UIView.setAnimationsEnabled(true)