UITableViewCell与iOS 7中的UITextView高度? [英] UITableViewCell with UITextView height in iOS 7?

查看:278
本文介绍了UITableViewCell与iOS 7中的UITextView高度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在iOS 7中使用UITableViewCell中的UITextView来计算UITableViewCell的高度?



我在类似问题上发现了很多答案,但<$ c



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

解决方案

首先,需要注意的是,UITextView和UILabel在文本呈现方式上有很大的区别。



因此, sizeWithFont:

而是 UITextView 本身有一个名为<$ c>的函数$ c> sizeThatFits:,它将返回在您可以指定的边界框内显示 UITextView 的所有内容所需的最小大小。 / p>

以下内容同样适用于iOS 7和旧版本,现在不包括任何已弃用的方法。






简单解决方案



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

此函数需要一个 NSAttributedString ,并将所需的宽度设为 CGFloat 并返回所需的高度



<

详细解决方案



由于我最近做了类似的事情,我想我也会分享一些解决方案, 。



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




  • 当然:基于显示所包含的 UITextView 的完整内容所需的大小设置 UITableViewCell code>

  • 对文本更改作出响应(并对该行的高度变化进行动画处理)

  • 将光标停留在可见区域内,编辑时调整 UITableViewCell 时调整 UITextView 时的第一个响应者



如果您使用静态表视图或者只有已知数量的 UITextView ,您可以步骤2要简单得多。



1。首先,覆盖heightForRowAtIndexPath:



   - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//检查这里,如果它是一个单元格,需要调整大小
//到包含的UITextView的大小
if()
return [self textViewHeightForRowAtIndexPath: indexPath];
else
//在这里返回你的正常高度:
return 100.0;
}



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



添加 NSMutableDictionary (在本例中称为

使用此字典,您可以将<> textViews UITextViews 的引用:



(是,indexPaths是字典的有效键

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
static NSString * CellIdentifier = @Cell
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

//你的单元格配置...

[textViews setObject:cell.textView forKey:indexPath];
[cell.textView setDelegate:self]; //需要步骤3

return cell;
}

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

   - (CGFloat)textViewHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITextView * calculationView = [textViews objectForKey:indexPath];
CGFloat textViewWidth = calculationView.frame.size.width;
if(!calculateView.attributedText){
//当文本视图没有被初始化时,这将是需要的

calculateView = [[UITextView alloc] init] ;
calculateView.attributedText = //从您的数据源获取文本添加属性并在此处插入
textViewWidth = 290.0; //插入你的UITextViews的宽度或包含相应的计算
}
CGSize size = [calculateView sizeThatFits:CGSizeMake(textViewWidth,FLT_MAX)];
return size.height;
}



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



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

   - (void)textViewDidChange:(UITextView *)textView {

[self.tableView beginUpdates]; //这将导致
的动画更新[self.tableView endUpdates]; // UITableViewCell的高度

//如果UITextView没有自动调整大小(例如通过autolayout
// constraints),请在这里调整大小

[self scrollToCursorForTextView:textView]; //可选:跟随游标
}



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; //在游标下添加一些空格
[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];
}



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






UPDATE:



正如Dave Haupert指出,我忘记了包含 rectVisible 函数: / p>

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


How can I calculate the height of an UITableViewCell with an UITextView in it in iOS 7?

I found a lot of answers on similar questions, but sizeWithFont: takes part in every solution and this method is deprecated!

I know I have to use - (CGFloat)tableView:heightForRowAtIndexPath: but how do I calculate the height my TextView needs to display the whole text?

解决方案

First of all, it is very important to note, that there is a big difference between UITextView and UILabel when it comes to how text is rendered. Not only does UITextView have insets on all borders, but also the text layout inside it is slightly different.

Therefore, sizeWithFont: is a bad way to go for UITextViews.

Instead UITextView itself has a function called sizeThatFits: which will return the smallest size needed to display all contents of the UITextView inside a bounding box, that you can specify.

The following will work equally for both iOS 7 and older versions and as of right now does not include any methods, that are deprecated.


Simple Solution

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

This function will take a NSAttributedString and the desired width as a CGFloat and return the height needed


Detailed Solution

Since I have recently done something similar, I thought I would also share some solutions to the connected Issues I encountered. I hope it will help somebody.

This is far more in depth and will cover the following:

  • Of course: setting the height of a UITableViewCell based on the size needed to display the full contents of a contained UITextView
  • Respond to text changes (and animate the height changes of the row)
  • Keeping the cursor inside the visible area and keeping first responder on the UITextView when resizing the UITableViewCell while editing

If you are working with a static table view or you only have a known number of UITextViews, you can potentially make step 2 much simpler.

1. First, overwrite the 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. Define the function that calculated the needed height:

Add an NSMutableDictionary (in this example called textViews) as an instance variable to your UITableViewController subclass.

Use this dictionary to store references to the individual UITextViews like so:

(and yes, 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;
}

This function will now calculate the actual height:

- (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. Enable Resizing while Editing

For the next two functions, it is important, that the delegate of the UITextViews is set to your UITableViewController. If you need something else as the delegate, you can work around it by making the relevant calls from there or using the appropriate NSNotificationCenter hooks.

- (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. Follow cursor while Editing

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

This will make the UITableView scroll to the position of the cursor, if it is not inside the visible Rect of the 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. Adjust visible rect, by setting insets

While editing, parts of your UITableView may be covered by the Keyboard. If the tableviews insets are not adjusted, scrollToCursorForTextView: will not be able to scroll to your cursor, if it is at the bottom of the 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];
}

And last part:

Inside your view did load, sign up for the Notifications for Keyboard changes through 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];
}

Please don't get mad at me, for making this answer so long. While not all of it is needed to answer the question, I believe that there are other people who these directly related issues will be helpful to.


UPDATE:

As Dave Haupert pointed out, I forgot to include the rectVisible function:

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

Also I noticed, that scrollToCursorForTextView: still included a direct reference to one of the TextFields in my project. If you have a problem with bodyTextView not being found, check the updated version of the function.

这篇关于UITableViewCell与iOS 7中的UITextView高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆