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

时间:2012-12-28 08:07:57

标签: ios tableview

我创建了一个像imessage的视图,只需在底部文本视图中输入文本。我使用表视图来执行此操作,并使用最后一个单元格中的文本视图。当我输入多行的长文本时,我需要文本视图,单元格变成了尾部。所以我需要刷新单元格的高度。但如果我使用表视图的重新加载或重新加载行,文本视图中的内容将消失,键盘也将消失。有没有更好的方法来解决它?

可能我应该使用工具栏轻松完成吗?但我仍然怀疑桌面视图可以做到。

4 个答案:

答案 0 :(得分:67)

当您致电beginUpdatesendUpdates时,小组会顺利调整大小。在这些调用之后,tableView将为表中的所有单元格发送tableView:heightForRowAtIndexPath:,当tableView获得所有单元格的所有高度时,它将为调整大小设置动画。

您可以通过直接设置单元格的属性来更新单元格而无需重新加载它们。无需涉及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];

答案 1 :(得分:2)

我编写了一个UITableViewCell的子类来处理这个功能。

.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创建一个UITableViewController
  2. 将一个单元格添加到作为AECELLSizeable(或其子类)的tableview中
  3. 在此单元格中创建两个UIView。一个UIView将用于最小化时可见的内容,另一个将用于最大化时可见的内容。确保这些单元格在y轴上从0开始,并且它们的高度等于您希望每个状态具有单元格的高度。
  4. 将所有子视图添加到您需要的这两个视图中。 (可选)添加确认并取消UIButtons到最大化的UIView并挂钩提供的IBActions以接收关于这些事件的委托回调。
  5. 将tableview控制器设置为符合AECELLSizeableDelegate,并将单元格的委托属性设置为tableview控制器。
  6. 在UIViewController的AECELLSizeable单元格的接口文件中创建一个IBOutlet。
  7. 返回IB,确保单元格的初始高度是最小化版本的高度,并连接您之前创建的IBOutlet。
  8. 在tableview控制器的实现文件中定义tableview的heightForRowAtIndexPath回调方法,如下所示:

    - (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方法中,调用单元格中的minimizeForTableview以确保它从最小化开始。

  10. 然后,当通过来自tableview的didSelectRowAtIndexPath回调选择它时,在单元格上调用maximizeForTableview :(或者你想要处理它),并在收到取消/确认的委托时调用单元格上的minimizeForTableview:方法来自单元格的回调(或者,无论如何,你想要处理它)。

答案 2 :(得分:-1)

结帐this library。这是使用UITableView的消息气泡的实现。请记住,每次显示一个单元格时,都会调用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;
}

答案 3 :(得分:-3)

表视图单元格不会平滑调整大小。点。

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

我将如何操作:将文本视图放在表格视图的顶部。将其位置与scrollViewDidScroll:中tableView的contentOffset同步。并使用tableView的动画contentInset,以便为用户输入textView留出空间。您可能必须确保textView不可滚动。