【问题标题】:iOS 8 auto-sizing UITableViewCell with UITextViewiOS 8 使用 UITextView 自动调整 UITableViewCell 的大小
【发布时间】:2014-11-05 14:56:00
【问题描述】:

iOS 8 为 tableViews 引入了一种方法,可以根据其内容(通过 AutoLayout)自动调整其单元格的高度。

// in viewDidLoad:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44.0

我已经可以处理标签、图像等了。

但是,我想不出一种方法让表格视图单元格在单元格的文本视图发生变化时自动增长?

有关设置的更多信息: 单元格内的 UITextView 对表格视图单元格的 contentView 具有水平和垂直约束。我还禁用了文本视图的滚动。

我也尝试手动更改单元格的高度约束,但单元格也不会采用这些更改。

【问题讨论】:

  • 那方面有什么进展吗?我也想做同样的事情......您是否试图在用户键入时让它工作?还是您使用的 UITextView 不是用户可编辑的?

标签: uitableview autolayout ios8


【解决方案1】:

如果一切设置正确(自动布局约束),您不必自己计算任何东西

您所要做的就是禁用 UITextView 的启用滚动属性,然后在 textViewDidChange 上调用 tableView.beginUpdates()tableView.endUpdates()

如需详细说明,请查看post I wrote,其中还包括一个工作示例项目。

【讨论】:

  • 它是否也适用于 UIWebView 而不是 UITextView ?
  • 我不确定,UIWebView可能有不同的布局过程,但值得一试!
  • 仅删除启用的滚动对我有用。谢谢:)
  • UITableViewController 中的静态单元格呢?
  • 我在“shouldChangeTextIn”中添加了这段代码并且工作正常。但不适用于新行,并且在键入字符后会增长 //textview 驻留在 tableview 单元格中
【解决方案2】:

UITextViewDelegatetextViewDidBeginEditing: 方法中重新加载单元格

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];

显然,您应该将索引路径更改为适合您的单元格的正确路径。这将使单元格更新其约束并调整自身大小。

【讨论】:

  • 即使没有reloadRowsAtIndexPaths:,它似乎也能工作,因为它有键盘的好处
  • 对我来说,这种方法会导致表格视图在每次击键时滚动回顶部,这使得文本视图基本上无法使用 - 其他人有这个问题吗? (iOS 8.1.2)
  • 我应该补充一下,我把这段代码放到了textViewDidChange:,而不是textViewDidBeginEditing:(无论如何只在开始编辑时设置高度有什么用?)
  • @James 如果您之前禁用动画并在摆脱烦人的弹跳之后重新启用。
【解决方案3】:

tableView 必须被告知 textView 已更改。其他帖子通常会回答“静态”textView 问题。但是,如果您在表格中键入,则单元格需要随着 textView 的增长而增长。 textView 通过禁用滚动来增长。单元通过将textView 的顶部和底部约束设置为单元的contentView 来增长。一旦表格加载,这将工作一次。但是要告诉tableView 实时增长,您必须在textViewdidChange 委托调用中进行

func textViewChanged(onCell cell: YourCustomCell) {
    UIView.setAnimationsEnabled(false)
    tableView.beginUpdates()
    tableView.endUpdates()
    UIView.setAnimationsEnabled(true)
}

这将按您的预期工作。单元格会随着您的输入而增长,并且不会出现“弹跳”。

【讨论】:

    【解决方案4】:

    Swift 4 解决方案

    func textViewDidChange(_ textView: UITextView) {
        let fixedWidth = textView.frame.size.width
        let oldSize = textView.frame.size
        let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT)))
        if oldSize.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            var newFrame = textView.frame
            newFrame.size = CGSize(width: fmax(newSize.width, fixedWidth), height: newSize.height)
            textView.frame = newFrame
            self.tableView.beginUpdates()
            self.tableView.endUpdates()
            UIView.setAnimationsEnabled(true)
        }
    }
    

    【讨论】:

      【解决方案5】:

      这是我使用的功能,解决了每次击键后表格视图弹回的问题。

       - (void)textViewDidChange:(UITextView *)textView {
      
          CGFloat fixedWidth = textView.frame.size.width;
          CGSize oldSize = textView.frame.size;
          CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
              // Resize cell only when cell's size changes, to prevent bouncing back and forth.
              if (oldSize.height != newSize.height) {
              [UIView setAnimationsEnabled:NO];
              CGRect newFrame = textView.frame;
              newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
              textView.frame = newFrame;
              [self.tableView beginUpdates];
              [self.tableView endUpdates];
              [UIView setAnimationsEnabled:YES];
              }
          }
      

      【讨论】:

      • 如果单元格位于底部并且您需要滚动到该点才能在开始编辑行时可见,会发生什么情况?
      • 是的,不幸的是我也遇到了这个问题。不知道如何解决它。
      【解决方案6】:

      你应该从你的 UITextView 禁用滚动

      【讨论】:

        猜你喜欢
        • 2014-09-25
        • 1970-01-01
        • 2014-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-18
        相关资源
        最近更新 更多