有没有办法刷新单元格的高度没有重载/ reloadRow?

我做了一个像imessage一样的视图,只需将文本input到底部的文本视图。 我使用表视图来做到这一点,并在最后一个单元格中的文本视图。 当我input不止一行的长文本时,我需要文本视图和单元格变成尾部。 所以我需要刷新细胞的高度。 但如果我使用表视图的重新加载或重新加载行,文本视图中的内容将消失,键盘也将消失。 有没有更好的解决办法?

可能是我应该使用工具栏来做到这一点容易吗? 但我仍然怀疑表格视图可以做到这一点。

当您调用beginUpdatesendUpdates时,单元格将顺利resize。 这些调用后,tableView将发送tableView:heightForRowAtIndexPath:对于表中的所有单元格,当tableView获得所有单元格的高度时,它将animationresize。

你也可以通过直接设置单元格的属性来更新单元格而不用重新加载单元格。 不需要涉及tableView和tableView:cellForRowAtIndexPath:

要调整单元格大小,您可以使用类似于此的代码

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { NSString *newText = [textView.text stringByReplacingCharactersInRange:range withString:text]; CGSize size = // calculate size of new text if ((NSInteger)size.height != (NSInteger)[self tableView:nil heightForRowAtIndexPath:nil]) { // if new size is different to old size resize cells. // since beginUpdate/endUpdates calls tableView:heightForRowAtIndexPath: for all cells in the table this should only be done when really necessary. [self.tableView beginUpdates]; [self.tableView endUpdates]; } return YES; } 

改变一个单元格的内容而不重新加载我使用这样的东西:

 - (void)configureCell:(FancyCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { MyFancyObject *object = ... cell.textView.text = object.text; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { FancyCell *cell = (FancyCell *)[tableView dequeueReusableCellWithIdentifier:@"CellWithTextView"]; [self configureCell:cell forRowAtIndexPath:indexPath]; return cell; } // whenever you want to change the cell content use something like this: NSIndexPath *indexPath = ... FancyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; [self configureCell:cell forRowAtIndexPath:indexPath]; 

我写了一个UITableViewCell的子类来处理这个function。

.h文件:

 #import <UIKit/UIKit.h> @protocol AECELLSizeableDelegate; @interface AECELLSizeable : UITableViewCell @property (weak, nonatomic) id <AECELLSizeableDelegate> delegate; @property IBOutlet UIView *viewMinimized; @property IBOutlet UIView *viewMaximized; @property BOOL maximized; @property CGFloat height; - (IBAction)clickedConfirm:(id)sender; - (IBAction)clickedCancel:(id)sender; - (void)minimizeForTableview: (UITableView*)tableView; - (void)maximizeForTableview: (UITableView*)tableView; - (void)toggleForTableview: (UITableView*)tableView; @end @protocol AECELLSizeableDelegate <NSObject> - (void)sizeableCellConfirmedForCell: (AECELLSizeable*)cell; - (void)sizeableCellCancelledForCell: (AECELLSizeable*)cell; @end 

.m文件:

 #import "AECELLSizeable.h" @implementation AECELLSizeable - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization code } return self; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } - (void)minimizeForTableview: (UITableView*)tableView { self.maximized = NO; [self.viewMinimized setHidden:NO]; [self.viewMaximized setHidden:YES]; self.height = self.viewMinimized.frame.size.height; [tableView beginUpdates]; [tableView endUpdates]; } - (void)maximizeForTableview: (UITableView*)tableView { self.maximized = YES; [self.viewMinimized setHidden:YES]; [self.viewMaximized setHidden:NO]; self.height = self.viewMaximized.frame.size.height; [tableView beginUpdates]; [tableView endUpdates]; } - (void)toggleForTableview:(UITableView *)tableView { if (self.maximized) { [self minimizeForTableview:tableView]; } else { [self maximizeForTableview:tableView]; } } - (void)clickedConfirm:(id)sender { [self.delegate sizeableCellConfirmedForCell:self]; } - (void)clickedCancel:(id)sender { [self.delegate sizeableCellCancelledForCell:self]; } @end 

用法示例:

  1. 在IB中使用静态UITableView创build一个UITableViewController
  2. 将一个单元格添加到AECELLSizeable(或其子类)的tableview中,
  3. 在这个单元格中创build两个UIViews。 一个UIView将用于可见内容而最小化,另一个将用于最大化可见内容。 确保这些单元格从y轴的0开始,并且它们的高度等于您希望为每个状态获得单元格的高度。
  4. 添加你想要的这两个视图的任何子视图。 可以select添加确认并取消UIButtons到最大化的UIView,并挂钩提供的IBActions接收这些事件的代理callback。
  5. 设置您的tableview控制器符合AECELLSizeableDelegate并将单元格的委托属性设置为tableview控制器。
  6. 在您的UIViewController的AECELLSizeable单元的接口文件中创build一个IBOutlet。
  7. 回到IB,确保单元的初始高度是最小化版本的高度,并连接您之前创build的IBOutlet。
  8. 在tableview控制器的实现文件中定义tableview的heightForRowAtIndexPathcallback方法,如下所示:

     - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { //Sizeable Cell return self.cellSizeable.height; } else { return [super tableView:tableView heightForRowAtIndexPath:indexPath]; } } 
  9. 在你的tableview控制器的viewDidLoad方法中,调用你的单元格的minimForTableview,以确保它开始最小化。

  10. 然后,调用maximizeForTableview:在通过tableview的didSelectRowAtIndexPathcallbackselect单元格时(或者您想要处理它),并在从单元格接收取消/确认的委托callback时调用单元格上的minimizeForTableview:方法细胞(或者,再次,但是你想要处理它)。

看看这个图书馆 。 这是使用UITableView的消息气泡的实现。 请记住,每次显示单元格时,都调用cellForRow:atIndexPath ,并cellForRow:atIndexPath单元格。

编辑

你可以使用heightForRowAtIndexPath

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { Messages *message = [self.messageList objectAtIndex:[indexPath row]]; CGSize stringSize = [message.text sizeWithFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:13] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap]; return stringSize.height + 78; } 

表格视图单元格不会平滑resize。 点。

但是,由于您的文本视图位于最后一个单元格中,因此您可以轻松地模拟行大小调整。 在表格中间显示文本视图会困难得多。

这是我将如何做到这一点:把你的文本视图放在表视图的顶部。 在scrollViewDidScroll:中将其位置与tableView的contentOffset同步。 并使用tableView的animationcontentInset为textView留出空间,当用户input它时。 您可能需要确保您的textView不可滚动。