有没有办法在不重新加载/重新加载行的情况下刷新单元格的高度?



我创建了一个像imessage这样的视图,只是在底部文本视图中输入文本。我使用表视图和最后一个单元格中的文本视图来做到这一点。当我输入超过一行的长文本时,我需要文本视图和单元格变得更小。所以我需要刷新单元格的高度。但如果我使用表格视图的重载行,文本视图中的内容会消失,键盘也会消失。有更好的办法来解决吗?

也许我应该使用工具栏来做到这一点?

当您调用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];

我已经写了一个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. 为tableview添加一个aecellsizing(或其子类)的单元格
  3. 在这个单元格中创建两个uiview。一个UIView将用于最小化时的可见内容,另一个将用于最大化时的可见内容。确保这些单元格从y轴上的0开始,并且它们的高度等于您希望每个状态的单元格的高度。
  4. 向这两个视图添加您想要的任何子视图。可选地添加确认和取消uibutton到最大化的UIView,并连接提供的IBActions来接收这些事件的委托回调。
  5. 设置你的表视图控制器符合AECELLSizeableDelegate,并设置单元格的delegate属性给表视图控制器。
  6. 在你的UIViewController的接口文件中为aecellsizable cell创建一个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. 然后,在单元格上调用maximizeForTableview:当它通过tableview的didSelectRowAtIndexPath回调被选中时(或者其他你想处理它的方法),并在单元格上调用minimizeForTableview:方法,当你从单元格收到取消/确认委托回调时(或者,再一次,无论你想处理它)。

查看这个库。这是一个使用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;
}

表格视图单元格无法顺利调整大小。点。

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

我是这样做的:把你的文本视图放在表格视图的顶部。与scrollViewDidScroll中tableView的contenttoffset同步它的位置。并使用tableView的animatable contentInset以便为textView留下空间,因为用户在其中键入。你可能需要确保你的textView是不可滚动的

最新更新