Iphone 如何制作内部带有UITextView的UITableViewCell,并根据UITextView动态调整其高度?

Iphone 如何制作内部带有UITextView的UITableViewCell,并根据UITextView动态调整其高度?,iphone,uitableview,uitextview,Iphone,Uitableview,Uitextview,我希望有一个tablew视图,其行为类似于Apple的iPhone Contacts应用程序:一个内部带有uitextview的uitableviewcell,这样当我在uitextview中写入时,uitextview会增加其高度,因此uitableviewcell会相应地动态调整其高度。我搜索了整个网页,只找到了部分解决方案,而且缺少示例代码 请帮帮我,我绝望了 Tony您需要在heightForRowAtIndexPath委托方法中返回正确的高度。考虑到这一点,您需要有些技巧。您需要动态计

我希望有一个tablew视图,其行为类似于Apple的iPhone Contacts应用程序:一个内部带有uitextview的uitableviewcell,这样当我在uitextview中写入时,uitextview会增加其高度,因此uitableviewcell会相应地动态调整其高度。我搜索了整个网页,只找到了部分解决方案,而且缺少示例代码

请帮帮我,我绝望了


Tony

您需要在heightForRowAtIndexPath委托方法中返回正确的高度。

考虑到这一点,您需要有些技巧。您需要动态计算textView的高度,并根据textView的高度返回单元格的高度

这很容易,有点棘手

这是您可以用来计算字符串大小的代码

首先得到字符串的大小

NSString *label =  @"Sample String to get the Size for the textView Will definitely work ";
CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15]
                      constrainedToSize:CGSizeMake(320, 9999)
                          lineBreakMode:UILineBreakModeWordWrap];

over here ....
NSLog(@"%f",stringSize.height);
其次,在单元格中动态创建textView..给出stringSize.height

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    //if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    //}

    NSDictionary *d=(NSDictionary *)[self.menuArray objectAtIndex:indexPath.section];

    NSString *string = [d valueForKey:@"Description"];
    CGSize stringSize = [string sizeWithFont:[UIFont boldSystemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap];

    UITextView *textV=[[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height+10)];
    textV.font = [UIFont systemFontOfSize:15.0];
    textV.text=string;
    textV.textColor=[UIColor blackColor];
    textV.editable=NO;
    [cell.contentView addSubview:textV];
    [textV release];

    return cell;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  {  

    NSDictionary *d=(NSDictionary *)[self.menuArray objectAtIndex:indexPath.section];
    NSString *label =  [d valueForKey:@"Description"];
    CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15]
                          constrainedToSize:CGSizeMake(320, 9999) 
                              lineBreakMode:UILineBreakModeWordWrap];

    return stringSize.height+25;

} 
在给我的手指带来这么多痛苦之后,…我认为这已经足够了代码…&肯定会帮助解决你的问题


祝您好运

您可以通过编程方式获取UITextView大小。根据大小,使用以下委托设置单元格的高度

tableView:heightForRowAtIndexPath:

创建自定义UITableViewCell并将UITextView添加到该单元格的contentView

在LayoutSubView中,将textView.frame设置为单元格的contentView.bounds(或执行其他一些自定义布局)

当textView内容更改(通过UITextViewDelegate发现)时,请执行两项操作:

1) 调用
[tableView BeginUpdate];[tableView EndUpdate]这将强制表格视图重新计算所有单元格的高度(将调用
表格视图:heightForRowAtIndexPath:
)。如果您的单元格是textView的委托,那么您必须找出如何获取指向tableView的指针,但有几种方法可以实现这一点。或者,您可以将代理作为您的视图控制器


2) 为此单元格调用
tableView:heightforrowatinexpath:
时,返回
textView.contentSize.height
。您可以通过调用
[tableView cellForRowAtIndexPath]从这里获取您的手机或者,如果你只有其中一个单元格,那么在你的viewController中缓存一个指向它的指针。

我终于让它工作了。主要问题是如何获得单元格的
contentView
正确宽度。硬编码宽度并不适用于所有情况,因为它可能会相应地改变普通/分组的桌子样式、添加的附件或横向/纵向布局。获得100%正确宽度的唯一方法是从单元对象请求宽度。所以我在
heightforrowatinexpath
中创建单元格,并将其存储在缓存中,然后该缓存单元格将由
cellforrowatinexpath
方法返回。
另一个问题是如何在使用单元之前强制单元布局其子视图。如果我们将单元格临时添加到
表视图中
,并使用
选项卡视图
的宽度更新单元格的框架,则可以完成此操作。之后,所有子视图都将以正确的方式进行布局。这是我如何在我的图书馆中使用它的。

我已经在我的博客上写下了我的学习和计算方法。这篇文章包含了适用于通用应用程序的代码,包括表视图样式和自动旋转。

伙计们,这真的很酷,但你可以使用tableview:didSelectRowForIndexPath:将UITextView作为用户点击时的子视图添加到单元格中,工作得非常好,因为您只需要使用1个UITextView,您可以重用它,并且不会干扰tableview接收触摸!完成后释放它


细节?问吧

请尝试以下代码:

CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = yourTextView.frame.size.width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont fontWithName:@"yourFontName" size:yourFontSize], NSFontAttributeName,
                                      nil];

CGRect frame = [yourTextView.text boundingRectWithSize:constraintSize
                                  options:NSStringDrawingUsesLineFragmentOrigin
                               attributes:attributesDictionary
                                  context:nil];

CGSize stringSize = frame.size;//The string size can be set to the UITableViewCell

我在接受的答案中发现的唯一问题是,我们每次都在分配UITextView。我发现这会引起在视图中键入内容、立即更新文本以及保持视图作为第一响应者的问题。当我尝试用新高度重新加载单元格时,它会尝试添加一个新的文本视图

因此,我找到了一种稍微不同的方法来实现相同的目标。希望这种不同的做法可以帮助那些努力实现上述代码的人

1) 在头文件中,为文本和textView的高度定义一个变量:

UITextView * _textView;
NSInteger _textHeight;
设置一个变量意味着,如果我们将文本加载到textView中,我们可以将视图加载到某个高度,这也降低了复杂性

2) 加载文本视图并将其添加到单元格中

_textView = [[UITextView alloc] init];
_textView.delegate = self;
_textView.returnKeyType = UIReturnKeyDone;
_textView.font = [UIFont fontWithName:@"Helvetica" size:16];

if (![_user metaStringForKey:bBioKey].length) {
    _textView.text = @"Placeholder text";
    _textView.textColor = [UIColor lightGrayColor];
}


- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath == 0) { // Add logic to choose the correct cell

        if (_textView.superview != cell) {

            [cell addSubview:_textView];     

            _textView.keepTopInset.equal = KeepRequired(7);
            _textView.keepBottomInset.equal = KeepRequired(7);
            _textView.keepRightInset.equal = KeepRequired(10);
            _textView.keepLeftInset.equal = KeepRequired(70);
            }
        }
    }
}
使用keeplayout使我们能够保持文本字段始终保持与单元格相同的高度。我们也只添加了一次UITextView

3) 添加代码以计算文本的高度

- (NSInteger)getHeightOfBio: (NSString *)text {

    UILabel * gettingSizeLabel = [[UILabel alloc] init];
    gettingSizeLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
    gettingSizeLabel.text = text;
    gettingSizeLabel.numberOfLines = 0;
    CGSize maximumLabelSize = CGSizeMake(240, 9999); // this width will be as per your requirement

    CGSize expectedSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

    return expectedSize.height;
}
我尝试了很多,发现这是最好的

4) 在单元格高度中添加一些逻辑,以利用这一点:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == 0) { // Set the height for our changing textView

        return 30 + [self getHeightOfBio:_textView.text];
    }

    return 44;
}
很明显,我们需要比文本高度高一点,所以我增加了一个额外的缓冲量,可以进行实验

5) 每次键入字符时刷新视图,以检查是否需要增加大小:

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

    if ([self getHeightOfText:textView.text] != _textHeight) {

       _textHeight = [self getHeightOfText:textView.text];

       [self.tableView beginUpdates];
       [self.tableView endUpdates];
    }
}
在本节中,我们将在用户每次键入文本时获得文本的高度

然后,尽管我们使用存储值并将当前值与存储值进行比较。显然,如果它们是相同的,那么刷新视图是没有意义的。如果它们不同,我们更新值,然后刷新表

这一点我在stackOverflow上找到了一个很好的答案,它显示了我们如何只刷新表的高度而不是单元格本身。为什么不需要刷新单元格?这意味着,一旦这被称为单元高度更新,它会很好地增加

无论如何,我发现它工作得非常好,而且非常简单,可以将它放在一起,也可以将不同的部分放到其他人的代码中

被接受的答案的支柱是皮拉格
class CommentaireTextViewCell: UITableViewCell,UITextViewDelegate {

@IBOutlet weak var textViewCom: UITextView!
weak var parentTableView:UITableView?

@IBOutlet weak var constraintTextViewTopMargin: NSLayoutConstraint!
@IBOutlet weak var constraintTextViewHeight: NSLayoutConstraint!
@IBOutlet weak var constraintTextViewBottomMargin: NSLayoutConstraint!
override func awakeFromNib() {
    self.textViewCom.delegate = self;
}

func textViewDidChange(textView: UITextView) {
    self.parentTableView?.beginUpdates();
    self.parentTableView?.endUpdates();
}

func getHeight() -> CGFloat
{
    constraintTextViewHeight.constant = self.textViewCom.contentSize.height;
    // cell height = textview marge top+ textview height+ textView Marge bottom
    return constraintTextViewTopMargin.constant+constraintTextViewHeight.constant+constraintTextViewBottomMargin.constant+8
    // add 8 because it seems to have an inset inside the textView
}

override func setSelected(selected: Bool, animated: Bool) {
    self.textViewCom.becomeFirstResponder();
}
}