iOS 8使用UITextView自动调整UITableViewCell的大小

时间:2022-03-13 08:17:30

iOS 8 introduced a way for tableViews to automatically adjust their cell's height based on their content (via AutoLayout).

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

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

I already got it working with labels, images, etc.

我已经使用了标签,图像等。

However, I can not figure out a way for the table view cell to grow automatically as soon as a cell's text view changes?

但是,一旦单元格的文本视图发生变化,我无法找到表格视图单元格自动增长的方法吗?

Some more information on the setup: The UITextView inside a cell has horizontal and vertical constraints to the table view cell's contentView. I also disabled scrolling for the text view.

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

I have also tried to change the height constraint of the cell manually, but the cell would not adopt those changes as well.

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

4 个解决方案

#1


21  

If everything is set up properly (Auto Layout constraints) you do not have to calculate anything yourself.

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

All you have to do is disable UITextView's scrolling enabled property then on textViewDidChange call tableView.beginUpdates() and tableView.endUpdates().

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

For a detailed explanation, check out a post I wrote which also includes a working sample project.

有关详细说明,请查看我写的帖子,其中还包括一个工作示例项目。

#2


4  

Reload the cell in the textViewDidBeginEditing: method of your UITextViewDelegate

在UITextViewDelegate的textViewDidBeginEditing:方法中重新加载单元格

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

Obviously you should change the indexpath to the correct one for your cell. This will get the cell to update its constraints and resize itself.

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

#3


1  

Solution for Swift 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)
    }
}

#4


0  

This is the function I use, which solves the problem of the table view bouncing back after every keystroke.

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

 - (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];
        }
    }

#1


21  

If everything is set up properly (Auto Layout constraints) you do not have to calculate anything yourself.

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

All you have to do is disable UITextView's scrolling enabled property then on textViewDidChange call tableView.beginUpdates() and tableView.endUpdates().

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

For a detailed explanation, check out a post I wrote which also includes a working sample project.

有关详细说明,请查看我写的帖子,其中还包括一个工作示例项目。

#2


4  

Reload the cell in the textViewDidBeginEditing: method of your UITextViewDelegate

在UITextViewDelegate的textViewDidBeginEditing:方法中重新加载单元格

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

Obviously you should change the indexpath to the correct one for your cell. This will get the cell to update its constraints and resize itself.

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

#3


1  

Solution for Swift 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)
    }
}

#4


0  

This is the function I use, which solves the problem of the table view bouncing back after every keystroke.

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

 - (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];
        }
    }