在iOS 7中具有UITextView高度的UITableViewCell?


121

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

我在类似问题上找到了很多答案,但是sizeWithFont:参与了每种解决方案,因此不赞成使用此方法!

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

Answers:


428

首先,需要特别注意的是,在文本呈现方式方面,UITextView和UILabel之间存在很大差异。UITextView不仅在所有边界上都有插图,而且其中的文本布局也略有不同。

因此,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;
}

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


详细解决方案

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

这要深入得多,将涵盖以下内容:

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

如果您使用的是静态表视图,或者只有已知的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.定义计算所需高度的函数:

NSMutableDictionarytextViews您的UITableViewController子类中添加一个(在此示例中称为)作为实例变量。

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

(是的,indexPaths是字典的有效键

- (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设置为your 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的可见Rect范围内,则将滚动到光标的位置:

- (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可能会被键盘覆盖。如果未调整表视图的插入scrollToCursorForTextView:,如果它位于表视图的底部,将无法滚动到光标。

- (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找不到问题,请检查该功能的更新版本。


1
该代码运行良好!它调整了一切!但是,我的TextView的高度总是30px!是否有不允许设置的设置,或者UITextView中不允许我使用的设置?
MyJBMe 2013年

1
如果文本很大,此解决方案似乎不适用于复制和粘贴,有什么想法吗?
维京人

2
@Tim Bodeit,您的解决方案有效,谢谢!但是我认为您应该在注释中注意,分配attributedText而不指定字体,颜色和文本对齐方式会导致将NSAttributedString属性的默认值设置为textView。就我而言,这会导致同一文本的textview高度不同。
亚历山大

4
这是我一直以来最喜欢的Stack Overflow答案之一-谢谢!
理查德·文布尔

3
@TimBodeit:我无法在iOS8上使用它。请让我知道如何解决此问题。
阿伦·古普塔

37

有一个新函数来替换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 )

当文本跨越3行时,我的UITextViews仍然不能很好地缩放并变得可滚动;pastebin.com/Wh6vmBqh
Martin de Keijzer 2013年

第二个return语句还会在XCode中引发弃用警告。
Martin de Keijzer 2013年

您是否还在cellForRowAtIndexPath中将UItextView的大小设置为计算出的文本大小?同样,您也不必担心第二次返回中的警告,因为它仅在应用程序在不弃用该功能的iOS6设备上运行时使用。
manecosta

您能否提供有关如何使用此功能的简单示例?
Zorayr

@manecosta苹果公司的文档说,您必须“限制”结果:在iOS 7及更高版本中,此方法返回小数大小(在返回的CGRect的大小部分中);要使用返回的大小调整视图大小,必须使用ceil函数将其值提高到最接近的较大整数。
HpTerm

9

如果您使用的是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,并且文本视图的预定义高度限制。

1
文本视图不能滚动
Akshit Zaveri

我一直在updateTextviewHeight下得到相同的大小。看起来内容大小是错误的。滚动被禁用。
德沃

5

蒂姆·博迪特(Tim Bodeit)的回答很好。我使用了简单解决方案的代码来正确获取文本视图的高度,并在中使用该高度heightForRowAtIndexPath。但是我不使用其余的答案来调整文本视图的大小。相反,我写的代码更改frame文本视图中cellForRowAtIndexPath

一切都可以在iOS 6及更低版本中使用,但在iOS 7中,即使frame确实调整了文本视图的大小,也无法完全显示文本视图中的文本。(我没有使用Auto Layout)。这可能是因为在iOS 7 TextKit中,文本的位置由NSTextContainerin 控制UITextView。因此,就我而言,我需要添加一行以设置someTextView,以使其在iOS 7中正常运行。

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

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

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

如果使用默认值,离开它,之后调整framesomeTextView,的大小textContainer不会更改,从而导致文本只能在调整大小之前显示在该区域中。

也许需要设置scrollEnabled = NOin,以防多个textContainer,以使文本从一个textContainer流向另一个。


4

这是另一种旨在简化和快速制作原型的解决方案:

建立:

  1. 带有原型单元的表格。
  2. 每个单元格包含具有UITextView其他内容的动态大小。
  3. 原型细胞与关联TableCell.h
  4. UITableView与关联TableViewController.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:。如注释中所述,由于size.height仅是文本视图的高度,而不是整个单元格的高度,因此应在其中添加一些偏移量。在示例的情况下,该值为80。


这个“ dream.dream”代表什么?
2013年

@MyJBMe对不起,这是我自己的项目的一部分-我已相应地更新了代码。dream.dream是我在文本视图中渲染的文本。
Zorayr

3

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

我回答了一个类似的问题,并提供了一个完整的示例,可以使用自动布局来调整tableview单元的大小,这里:

如何调整超级视图的大小以适合具有自动布局的所有子视图?


1

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

首先,我们需要带有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的最小高度(以防止通过UITableViewAutomaticDimension自动布局使高度最小化)。

  • moveRowAtIndexPath:indexPath: 具有相同indexPath的表将重新计算tableViewCell高度并重新布局。

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

  • 重要的是在单元格更新期间保留relativeFrameOriginY(而不是 contentOffsetY!),因为contentSize当前单元格之前的单元格可以通过autoLayout演算以意想不到的方式更改。键入长字时,它消除了系统连字时的视觉跳动。

  • 请注意,您不应该设置该属性 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


0
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;

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


0

迅捷版

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
}

0

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

解决的办法很简单,因为iOS的应该工作肯定7.确保该Scrolling Enabled选项被关闭UITextView里面的UITableViewCell故事板。

然后在UITableViewController的viewDidLoad()中设置tableView.rowHeight = UITableViewAutomaticDimension和,tableView.estimatedRowHeight > 0例如:

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 44.0
}

而已。UITableViewCell的高度将根据内部UITextView高度自动调整。


-2

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

your_tablview.estimatedrowheight= minheight 你要

your_tableview.rowheight=UItableviewautomaticDimension
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.