【问题标题】:UITableViewCell with UITextView height in iOS 7?iOS 7 中具有 UITextView 高度的 UITableViewCell?
【发布时间】:2013-08-24 11:35:00
【问题描述】:

如何在 iOS 7 中计算带有 UITextView 的 UITableViewCell 的高度?

我找到了很多类似问题的答案,但是sizeWithFont: 参与了每个解决方案,并且这种方法已被弃用!

我知道我必须使用- (CGFloat)tableView:heightForRowAtIndexPath:,但是如何计算 TextView 显示整个文本所需的高度?

【问题讨论】:

    标签: cocoa-touch uitableview height ios7


    【解决方案1】:

    首先,需要注意的是,UITextView 和 UILabel 在文本呈现方式上存在很大差异。 UITextView 不仅所有边框都有 insets,而且里面的文字布局也略有不同。

    因此,sizeWithFont: 对于 UITextViews 来说是个坏方法。

    UITextView 本身有一个名为sizeThatFits: 的函数,它将返回在您可以指定的边界框内显示UITextView 的所有内容所需的最小尺寸。

    以下内容同样适用于 iOS 7 和更早版本,并且目前不包含任何已弃用的方法。


    简单的解决方案

    - (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
        UITextView *calculationView = [[UITextView alloc] init];
        [calculationView setAttributedText:text];
        CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
        return size.height;
    }
    

    此函数将采用 NSAttributedString 和所需的宽度作为 CGFloat 并返回所需的高度


    详细解决方案

    由于我最近做了类似的事情,我想我也会分享一些我遇到的相关问题的解决方案。我希望它会对某人有所帮助。

    这更深入,将涵盖以下内容:

    • 当然:根据显示包含的UITextView 的全部内容所需的大小设置UITableViewCell 的高度
    • 响应文本变化(并为行的高度变化设置动画)
    • 在编辑时调整 UITableViewCell 的大小时,将光标保持在可见区域内并将第一响应者保持在 UITextView

    如果您使用的是静态表格视图,或者您只有已知数量的UITextViews,您可以使第 2 步更简单。

    1。首先,覆盖heightForRowAtIndexPath:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        // check here, if it is one of the cells, that needs to be resized
        // to the size of the contained UITextView
        if (  )             
            return [self textViewHeightForRowAtIndexPath:indexPath];
        else
        // return your normal height here:
                return 100.0;           
    }
    

    2。定义计算所需高度的函数:

    NSMutableDictionary(在此示例中称为textViews)作为实例变量添加到您的UITableViewController 子类。

    使用此字典存储对个人 UITextViews 的引用,如下所示:

    (是的,indexPaths are valid keys for dictionaries

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        
        // Do you cell configuring ...
    
        [textViews setObject:cell.textView forKey:indexPath];
        [cell.textView setDelegate: self]; // Needed for step 3
    
        return cell;
    }
    

    这个函数现在将计算实际高度:

    - (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
        UITextView *calculationView = [textViews objectForKey: indexPath];
        CGFloat textViewWidth = calculationView.frame.size.width;
        if (!calculationView.attributedText) {
            // This will be needed on load, when the text view is not inited yet
            
            calculationView = [[UITextView alloc] init];
            calculationView.attributedText = // get the text from your datasource add attributes and insert here
            textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
        }
        CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
        return size.height;
    }
    

    3。在编辑时启用调整大小

    对于接下来的两个函数,重要的是UITextViews 的委托设置为您的UITableViewController。如果您需要其他东西作为委托,您可以通过从那里进行相关调用或使用适当的 NSNotificationCenter 挂钩来解决它。

    - (void)textViewDidChange:(UITextView *)textView {
    
        [self.tableView beginUpdates]; // This will cause an animated update of
        [self.tableView endUpdates];   // the height of your UITableViewCell
    
        // If the UITextView is not automatically resized (e.g. through autolayout 
        // constraints), resize it here
    
        [self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
    }
    

    4。编辑时跟随光标

    - (void)textViewDidBeginEditing:(UITextView *)textView {
        [self scrollToCursorForTextView:textView];
    }
    

    这将使UITableView滚动到光标的位置,如果它不在UITableView的可见矩形内:

    - (void)scrollToCursorForTextView: (UITextView*)textView {
        
        CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];
        
        cursorRect = [self.tableView convertRect:cursorRect fromView:textView];
        
        if (![self rectVisible:cursorRect]) {
            cursorRect.size.height += 8; // To add some space underneath the cursor
            [self.tableView scrollRectToVisible:cursorRect animated:YES];
        }
    }
    

    5。通过设置插图调整可见矩形

    编辑时,您的UITableView 的部分内容可能会被键盘覆盖。如果 tableviews insets 没有调整,scrollToCursorForTextView: 将无法滚动到您的光标,如果它位于 tableview 的底部。

    - (void)keyboardWillShow:(NSNotification*)aNotification {
        NSDictionary* info = [aNotification userInfo];
        CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
        self.tableView.contentInset = contentInsets;
        self.tableView.scrollIndicatorInsets = contentInsets;
    }
    
    - (void)keyboardWillHide:(NSNotification*)aNotification {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.35];
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
        self.tableView.contentInset = contentInsets;
        self.tableView.scrollIndicatorInsets = contentInsets;
        [UIView commitAnimations];
    }
    

    最后一部分:

    在您的视图中确实加载了,通过NSNotificationCenter 注册键盘更改通知:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    }
    

    请不要生我的气,因为我回答了这么久。虽然不是所有问题都需要回答这个问题,但我相信这些直接相关的问题会对其他人有所帮助。


    更新:

    正如 Dave Haupert 指出的,我忘记包含 rectVisible 函数:

    - (BOOL)rectVisible: (CGRect)rect {
        CGRect visibleRect;
        visibleRect.origin = self.tableView.contentOffset;
        visibleRect.origin.y += self.tableView.contentInset.top;
        visibleRect.size = self.tableView.bounds.size;
        visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
        
        return CGRectContainsRect(visibleRect, rect);
    }
    

    我还注意到,scrollToCursorForTextView: 仍然包含对我项目中的一个 TextField 的直接引用。如果您对找不到bodyTextView 有问题,请检查该函数的更新版本。

    【讨论】:

    • 该代码运行良好!它调整一切!但是,我的 TextView 总是得到 30px 的高度!是否有我不允许设置的设置,或者我在 UITextView 中不允许设置的内容?
    • 如果文本很大,此解决方案似乎不适用于复制和粘贴,有什么想法吗?
    • @Tim Bodeit,您的解决方案有效,谢谢!但我认为您应该在评论中注意,在不指定字体、颜色和文本对齐方式的情况下分配 attributedText 会导致将 NSAttributedString 属性的默认值设置为 textView。在我的情况下,它会导致同一文本的文本视图高度不同。
    • 这是我一直以来最喜欢的 Stack Overflow 答案之一 - 谢谢!
    • @TimBodeit:我无法在 iOS8 上使用它。请让我知道如何解决此问题。
    【解决方案2】:

    有一个新的函数来代替sizeWithFont,即boundingRectWithSize。

    我在我的项目中添加了以下函数,它利用了iOS7上的新函数和低于7的iOS上的旧函数。它的语法与sizeWithFont基本相同:

        -(CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
            if(IOS_NEWER_OR_EQUAL_TO_7){
                NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                                  font, NSFontAttributeName,
                                                  nil];
    
                CGRect frame = [text boundingRectWithSize:size
                                                  options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                               attributes:attributesDictionary
                                                  context:nil];
    
                return frame.size;
            }else{
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
                return [text sizeWithFont:font constrainedToSize:size];
    #pragma clang diagnostic pop
            }
        }
    

    您可以将 IOS_NEWER_OR_EQUAL_TO_7 添加到项目中的 prefix.pch 文件中:

    #define IOS_NEWER_OR_EQUAL_TO_7 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 7.0 )
    

    【讨论】:

    • 我的 UITextViews 仍然不能很好地缩放并且当文本跨越 3 行时变得可滚动; pastebin.com/Wh6vmBqh
    • 第二个 return 语句也会在 XCode 中引发弃用警告。
    • 您是否还将 UItextView 的大小设置为计算出的文本大小,在 cellForRowAtIndexPath 中?此外,您不必担心第二次返回中的警告,因为它仅在应用程序在未弃用该功能的 iOS6 设备上运行时使用。
    • 你能提供一个如何使用这个函数的简单例子吗?
    • @manecosta Apple 的文档说您必须“限制”结果:在 iOS 7 及更高版本中,此方法返回小数大小(在返回的 CGRect 的大小组件中);要使用返回的大小来调整视图大小,您必须使用 ceil 函数将其值提高到最接近的较高整数。
    【解决方案3】:

    如果您使用的是 UITableViewAutomaticDimension,我有一个非常简单(仅限 iOS 8)的解决方案。在我的情况下,它是一个静态表格视图,但我想你可以将它用于动态原型......

    我有一个文本视图高度的约束出口,我已经实现了以下方法:

    // Outlets
    
    @property (weak, nonatomic) IBOutlet UITextView *textView;
    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeight;
    
    
    // Implementation
    
    #pragma mark - Private Methods
    
    - (void)updateTextViewHeight {
        self.textViewHeight.constant = self.textView.contentSize.height + self.textView.contentInset.top + self.textView.contentInset.bottom;
    }
    
    #pragma mark - View Controller Overrides
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self updateTextViewHeight];
    }
    
    #pragma mark - TableView Delegate & Datasource
    
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return 80;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return UITableViewAutomaticDimension;
    }
    
    #pragma mark - TextViewDelegate
    
    - (void)textViewDidChange:(UITextView *)textView {
        [self.tableView beginUpdates];
        [self updateTextViewHeight];
        [self.tableView endUpdates];
    }
    

    但请记住:文本视图必须是可滚动的,并且您必须设置约束以使其适用于自动尺寸:

    • 设置单元格中的所有视图相互关联,高度固定(包括文本视图高度,您将以编程方式更改)
    • 最顶部的视图具有顶部间距,最底部的视图具有与超级视图的底部间距;

    最基本的单元格示例是:

    • 单元格中除了 textview 没有其他视图
    • 文本视图四周的边距为 0,并且文本视图的预定义高度约束。

    【讨论】:

    • 文本视图必须可滚动
    • 我在 updateTextviewHeight 下一直得到相同的大小。看起来内容大小是错误的。滚动已禁用。
    【解决方案4】:

    Tim Bodeit 的回答很棒。我使用简单解决方案的代码来正确获取文本视图的高度,并在heightForRowAtIndexPath 中使用该高度。但我不使用其余答案来调整文本视图的大小。相反,我编写代码来更改cellForRowAtIndexPath 中文本视图的frame

    在 iOS 6 及更低版本中一切正常,但在 iOS 7 中,即使文本视图的 frame 确实调整了大小,文本视图中的文本也无法完全显示。 (我没有使用Auto Layout)。应该是iOS 7中有TextKit的原因,文字的位置是由UITextView中的NSTextContainer控制的。因此,在我的情况下,我需要添加一行来设置 someTextView 以使其在 iOS 7 中正常工作。

        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
            someTextView.textContainer.heightTracksTextView = YES;
        }
    

    正如文档所说,该属性的作用是:

    控制接收器是否调整其边界的高度 调整其文本视图大小时的矩形。默认值:否。

    如果保留默认值,则在调整someTextViewframe的大小后,textContainer的大小不会改变,导致文本只能显示在调整大小之前的区域。

    如果有多个textContainer,则可能需要设置scrollEnabled = NO,以便文本从一个textContainer重排到另一个。

    【讨论】:

      【解决方案5】:

      这是另一个旨在简单和快速原型设计的解决方案

      设置:

      1. 带有原型单元格的表格。
      2. 每个单元格包含动态大小的UITextView 和其他内容。
      3. 原型单元格与TableCell.h 相关联。
      4. UITableViewTableViewController.h 相关联。

      解决方案:

      (1) 添加到TableViewController.m:

       // This is the method that determines the height of each cell.  
      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
      {
          // I am using a helper method here to get the text at a given cell.
          NSString *text = [self getTextAtIndex:indexPath];
      
          // Getting the height needed by the dynamic text view.
          CGSize size = [self frameForText:text sizeWithFont:nil constrainedToSize:CGSizeMake(300.f, CGFLOAT_MAX)];
      
          // Return the size of the current row.
          // 80 is the minimum height! Update accordingly - or else, cells are going to be too thin.
          return size.height + 80; 
      }
      
      // Think of this as some utility function that given text, calculates how much 
      // space would be needed to fit that text.
      - (CGSize)frameForText:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
      {
          NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                                font, NSFontAttributeName,
                                                nil];
          CGRect frame = [text boundingRectWithSize:size
                                            options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                         attributes:attributesDictionary
                                            context:nil];
      
          // This contains both height and width, but we really care about height.
          return frame.size;
      }
      
      // Think of this as a source for the text to be rendered in the text view. 
      // I used a dictionary to map indexPath to some dynamically fetched text.
      - (NSString *) getTextAtIndex: (NSIndexPath *) indexPath
      {
          return @"This is stubbed text - update it to return the text of the text view.";
      }
      

      (2) 添加到TableCell.m:

      // This method will be called when the cell is initialized from the storyboard
      // prototype. 
      - (void)awakeFromNib
      {
          // Assuming TextView here is the text view in the cell. 
          TextView.scrollEnabled = YES;
      }
      

      说明:

      所以这里发生的事情是这样的:每个文本视图都通过垂直和水平约束绑定到表格单元格的高度 - 这意味着当表格单元格高度增加时,文本视图也会增加其大小。我使用@manecosta 代码的修改版本来计算文本视图所需的高度以适合单元格中的给定文本。这意味着给定一个包含 X 个字符的文本,frameForText: 将返回一个大小,该大小将具有与文本视图所需高度匹配的属性 size.height

      现在,剩下的就是更新单元格的高度以匹配所需的文本视图的高度。这是在heightForRowAtIndexPath: 实现的。如 cmets 中所述,由于 size.height 只是文本视图的高度而不是整个单元格,因此应该添加一些偏移量。在示例的情况下,此值为 80。

      【讨论】:

      • 这个“dream.dream”代表什么?
      • @MyJBMe 抱歉,这是我自己项目的一部分——我已经相应地更新了代码。 dream.dream 是我在文本视图中呈现的文本。
      【解决方案6】:

      如果您使用自动布局,一种方法是让自动布局引擎为您计算尺寸。这不是最有效的方法,但它非常方便(并且可以说是最准确的)。随着单元布局复杂性的增加,它变得更加方便 - 例如突然你的单元格中有两个或多个文本视图/字段。

      我回答了一个类似的问题,这里有一个使用自动布局调整表格视图单元大小的完整示例:

      How to resize superview to fit all subviews with autolayout?

      【讨论】:

        【解决方案7】:

        完整的平滑解决方案如下。

        首先,我们需要带有 textView 的单元格类

        @protocol TextInputTableViewCellDelegate <NSObject>
        @optional
        - (void)textInputTableViewCellTextWillChange:(TextInputTableViewCell *)cell;
        - (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell;
        @end
        
        @interface TextInputTableViewCell : UITableViewCell
        @property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
        @property (nonatomic, readonly) UITextView *textView;
        @property (nonatomic) NSInteger minLines;
        @property (nonatomic) CGFloat lastRelativeFrameOriginY;
        @end
        
        
        #import "TextInputTableViewCell.h"
        
        @interface TextInputTableViewCell () <UITextViewDelegate> {
            NSLayoutConstraint *_heightConstraint;
        }
        @property (nonatomic) UITextView *textView;
        @end
        
        @implementation TextInputTableViewCell
        
        - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
            self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
            if (self) {
                self.selectionStyle = UITableViewCellSelectionStyleNone;
        
                _textView = [UITextView new];
                _textView.translatesAutoresizingMaskIntoConstraints = NO;
                _textView.delegate = self;
                _textView.scrollEnabled = NO;
                _textView.font = CELL_REG_FONT;
                _textView.textContainer.lineFragmentPadding = 0.0;
                _textView.textContainerInset = UIEdgeInsetsZero;
                [self.contentView addSubview:_textView];
        
                [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
                [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        
                _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                                 attribute: NSLayoutAttributeHeight
                                 relatedBy: NSLayoutRelationGreaterThanOrEqual
                                 toItem: nil
                                 attribute: NSLayoutAttributeNotAnAttribute
                                 multiplier: 0.0
                                 constant: (_textView.font.lineHeight + 15)];
                _heightConstraint.priority = UILayoutPriorityRequired - 1;
                [_textView addConstraint:_heightConstraint];
            }
            return self;
        }
        
        - (void)prepareForReuse {
            [super prepareForReuse];    
            self.minLines = 1;
        }
        
        - (void)setMinLines:(NSInteger)minLines {
            _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
        }
        
        - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
            if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextWillChange:)]) {
                [self.delegate textInputTableViewCellTextWillChange:self];
            }
            return YES;
        }
        
        - (void)textViewDidChange:(UITextView *)textView {
            if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextDidChange:)]) {
                [self.delegate textInputTableViewCellTextDidChange:self];
            }
        }
        

        接下来,我们在 TableViewController 中使用它

        @interface SomeTableViewController () <TextInputTableViewCellDelegate>
        @end
        
        @implementation SomeTableViewController
        
        . . . . . . . . . . . . . . . . . . . .
        
        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        
            TextInputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: TextInputTableViewCellIdentifier forIndexPath:indexPath];
            cell.delegate = self;
            cell.minLines = 3;
            . . . . . . . . . .  
            return cell;
        }
        
        - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
            return UITableViewAutomaticDimension;
        }
        
        - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
            return UITableViewAutomaticDimension;
        }
        
        - (void)textInputTableViewCellWillChange:(TextInputTableViewCell *)cell {
            cell.lastRelativeFrameOriginY = cell.frame.origin.y - self.tableView.contentOffset.y;
        }
        
        - (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell {
            NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        
            [UIView performWithoutAnimation:^{
                [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
            }];
        
            CGFloat contentOffsetY = cell.frame.origin.y - cell.lastRelativeFrameOriginY;
            self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);
        
            CGRect caretRect = [cell.textView caretRectForPosition:cell.textView.selectedTextRange.start];
            caretRect = [self.tableView convertRect:caretRect fromView:cell.textView];
        
            CGRect visibleRect = self.tableView.bounds;
            visibleRect.origin.y += self.tableView.contentInset.top;
            visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
            BOOL res = CGRectContainsRect(visibleRect, caretRect);
            if (!res) {
                caretRect.size.height += 5;
                [self.tableView scrollRectToVisible:caretRect animated:NO];
            }
        }
        @end
        
        • 这里minLines 允许为 textView 设置最小高度(到 通过 AutoLayout 抵抗高度最小化 UITableViewAutomaticDimension)。

        • moveRowAtIndexPath:indexPath: 以相同的 indexPath 开始 tableViewCell 高度重新计算和重新布局。

        • performWithoutAnimation: 移除副作用(tableView 内容 键入时在开始新行时偏移跳跃)。

        • 保留relativeFrameOriginY(不是 contentOffsetY!) 在单元格更新期间,因为 contentSize 的 当前单元格之前的单元格可以通过自动布局演算进行更改 以意想不到的方式。它消除了系统断字的视觉跳跃 在输入长字时。

        • 请注意,您不应该设置属性 estimatedRowHeight 以下不起作用

          self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
          

          仅使用 tableViewDelegate 方法。

        ================================================ =============================

        如果不介意 tableViewtableViewCell 之间的弱绑定以及从 tableViewCell 更新 tableView 的几何图形,则可以升级TextInputTableViewCell以上类:

        @interface TextInputTableViewCell : UITableViewCell
        @property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
        @property (nonatomic, weak) UITableView *tableView;
        @property (nonatomic, readonly) UITextView *textView;
        @property (nonatomic) NSInteger minLines;
        @end
        
        
        #import "TextInputTableViewCell.h"
        
        @interface TextInputTableViewCell () <UITextViewDelegate> {
            NSLayoutConstraint *_heightConstraint;
            CGFloat _lastRelativeFrameOriginY;
        }
        @property (nonatomic) UITextView *textView;
        @end
        
        @implementation TextInputTableViewCell
        
        - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
            self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
            if (self) {
                self.selectionStyle = UITableViewCellSelectionStyleNone;
        
                _textView = [UITextView new];
                _textView.translatesAutoresizingMaskIntoConstraints = NO;
                _textView.delegate = self;
                _textView.scrollEnabled = NO;
                _textView.font = CELL_REG_FONT;
                _textView.textContainer.lineFragmentPadding = 0.0;
                _textView.textContainerInset = UIEdgeInsetsZero;
                [self.contentView addSubview:_textView];
        
                [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
                [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        
                _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                                 attribute: NSLayoutAttributeHeight
                                 relatedBy: NSLayoutRelationGreaterThanOrEqual
                                 toItem: nil
                                 attribute: NSLayoutAttributeNotAnAttribute
                                 multiplier: 0.0
                                 constant: (_textView.font.lineHeight + 15)];
                _heightConstraint.priority = UILayoutPriorityRequired - 1;
                [_textView addConstraint:_heightConstraint];
            }
            return self;
        }
        
        - (void)prepareForReuse {
            [super prepareForReuse];    
            self.minLines = 1;
            self.tableView = nil;
        }
        
        - (void)setMinLines:(NSInteger)minLines {
            _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
        }
        
        - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
        
            _lastRelativeFrameOriginY = self.frame.origin.y - self.tableView.contentOffset.y;
            return YES;
        }
        
        - (void)textViewDidChange:(UITextView *)textView {
        
            NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
            if (indexPath == nil) return;
        
            [UIView performWithoutAnimation:^{
                [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
            }];
        
            CGFloat contentOffsetY = self.frame.origin.y - _lastRelativeFrameOriginY;
            self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);
        
            CGRect caretRect = [self.textView caretRectForPosition:self.textView.selectedTextRange.start];
            caretRect = [self.tableView convertRect:caretRect fromView:self.textView];
        
            CGRect visibleRect = self.tableView.bounds;
            visibleRect.origin.y += self.tableView.contentInset.top;
            visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
        
            BOOL res = CGRectContainsRect(visibleRect, caretRect);
            if (!res) {
                caretRect.size.height += 5;
                [self.tableView scrollRectToVisible:caretRect animated:NO];
            }
        }
        @end
        

        【讨论】:

          【解决方案8】:
          1. 将 UILabel 放在 UITextView 后面。
          2. 使用这个答案:https://stackoverflow.com/a/36054679/6681462 给你创建的 UILabel
          3. 给他们相同的约束和字体
          4. 将它们设置为相同的文本;

          你的单元格的高度将由 UILabel 的内容计算,但所有文本将由 TextField 显示。

          【讨论】:

            【解决方案9】:
            UITextView *txtDescLandscape=[[UITextView alloc] initWithFrame:CGRectMake(2,20,310,2)];
            
                txtDescLandscape.editable =NO;
                txtDescLandscape.textAlignment =UITextAlignmentLeft;
                [txtDescLandscape setFont:[UIFont fontWithName:@"ArialMT" size:15]];
                txtDescLandscape.text =[objImage valueForKey:@"imgdescription"];
                txtDescLandscape.text =[txtDescLandscape.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                [txtDescLandscape sizeToFit];
                [headerView addSubview:txtDescLandscape];
            
                CGRect txtViewlandscpframe = txtDescLandscape.frame;
                txtViewlandscpframe.size.height = txtDescLandscape.contentSize.height;
                txtDescLandscape.frame = txtViewlandscpframe;
            

            我认为这样您可以计算文本视图的高度,然后根据该高度调整表格视图单元格的大小,以便您可以在单元格上显示全文

            【讨论】:

              【解决方案10】:

              斯威夫特版本

              func textViewHeightForAttributedText(text: NSAttributedString, andWidth width: CGFloat) -> CGFloat {
                  let calculationView = UITextView()
                  calculationView.attributedText = text
                  let size = calculationView.sizeThatFits(CGSize(width: width, height: CGFloat.max))
                  return size.height
              }
              

              【讨论】:

                【解决方案11】:

                如果要根据内部UITextView的高度自动调整UITableViewCell的高度。在这里查看我的答案:https://stackoverflow.com/a/45890087/1245231

                该解决方案非常简单,从 iOS 7 开始应该可以使用。确保为 StoryBoard 中的 UITableViewCell 内的 UITextView 关闭了Scrolling Enabled 选项关闭

                然后在你的 UITableViewController 的 viewDidLoad() 中设置tableView.rowHeight = UITableViewAutomaticDimensiontableView.estimatedRowHeight &gt; 0 如:

                override func viewDidLoad() {
                    super.viewDidLoad()
                
                    tableView.rowHeight = UITableViewAutomaticDimension
                    tableView.estimatedRowHeight = 44.0
                }
                

                就是这样。 UITableViewCell的高度会根据内部UITextView的高度自动调整。

                【讨论】:

                  【解决方案12】:

                  对于 iOS 8 及更高版本,您可以使用

                  your_tablview.estimatedrowheight= minheight你想要的

                  your_tableview.rowheight=UItableviewautomaticDimension
                  

                  【讨论】:

                    猜你喜欢
                    • 2013-09-02
                    • 2011-06-20
                    • 2011-04-24
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-10-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-10-19
                    相关资源
                    最近更新 更多