【问题标题】:Variable TableViewCell height without AutoLayout没有自动布局的可变 TableViewCell 高度
【发布时间】:2020-12-06 03:12:10
【问题描述】:

我有一个基于UITableView的超古老Objective-C聊天代码。只有一种类型的单元格,我们称之为ChatTableViewCell。在我们的聊天中有超过 10 种类型的消息(文本、图像、事件等)。 ChatTableViewCell本身负责一堆逻辑,比如:

  • 在哪一侧显示头像(传入或传出消息);
  • 如果头像是来自同一用户的第二条以上消息,则隐藏头像(消息分组);
  • 对带有表情符号的消息的反应(用户可以对任何类型的消息作出反应);
  • 标签显示外发邮件的传递状态; – 等等。

ChatTableViewCell 还包含一个容器视图,其中添加了所需的UIView 子类(ImageMessageViewTextMessageViewEventMessageView)作为子视图。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 方法消息由消息数组中的索引获取。 今天之前,每个消息对象都将包含所有信息,像消息文本一样显示在单元格中,或者,如果它是事件消息,例如,它将包含所有信息项,例如位置名称、时间、日期、回复的人数等。

聊天代码是一种极端的遗留物,没有任何地方使用自动布局根本没有。 每个单元格高度在 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 在此方法中,消息由其索引获取,并根据其类型,将消息传递给所需的 UIView 子类的静态方法(嵌入到ChatTableViewCell)。那些静态方法有一个丑陋的手动高度计算,如下所示:

+ (CGSize)neededSizeForContentWithEventInfo:(SBEventInfo *)eventInfo
{
    CGFloat contentHeight = 0;
    
    UILabel *label = [SBEventBubbleView labelForType:LabelTypeIcon];
    label.text = @"????";
    CGRect frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    label = [SBEventBubbleView labelForType:LabelTypeTitle];
    label.text = eventInfo.name;
    frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    label = [SBEventBubbleView labelForType:LabelTypeTime];
    label.text = eventInfo.time;
    frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    label = [SBEventBubbleView labelForType:LabelTypeAddress];
    label.text = eventInfo.address;
    frame = [SBEventBubbleView frameForLabelText:label];
    contentHeight += frame.size.height;
    
    contentHeight += kEventBubblePaddingTop + kEventBubblePaddingBottom;
    
    contentHeight += (kEventBubbleContainersSpace + kEventBubbleButtonHeight);
    
    return CGSizeMake([SBEventBubbleView maxWidth], contentHeight);
}

+ (CGRect)frameForLabelText:(UILabel *)label
{
    return [label.text boundingRectWithSize:CGSizeMake([SBEventBubbleView maxWidth] - kEventBubblePaddingLeft - kEventBubblePaddingRight, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:nil];
}

问题:

现在有一种新型消息不包含所有现成的信息。取而代之的是,它只包含一些 ID,将其传递给 UIView 的相应子类,然后在这个视图内部有一个网络调用,它使用这个 ID 来获取所有信息。有了这个异步调用,就无法使用带有静态方法的丑陋老式方法来计算此消息在屏幕上的高度。

在这种情况下我该怎么办?是否可以从

返回一些临时/虚拟高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath```

然后,当单元格中的网络调用完成时,以某种方式重新计算具有所有可用数据的单元格的高度?

再一次,所有这些代码都是完全基于框架的,不幸的是,根本没有使用 AutoLayout。 否则,这将是一个微不足道的问题。

任何帮助将不胜感激!如果您想提供帮助但不完全理解问题,请询问更多信息。

【问题讨论】:

标签: ios objective-c uitableview autolayout


【解决方案1】:

tableView(_:heightForRowAt:) 中,返回您还没有数据的行的估计高度。获取一行数据后,调用tableView.reloadRows(at:with:)

当表格视图重新加载行时,它会再次调用tableView(_:heightForRowAt:)委托方法,您可以返回正确的高度。

【讨论】:

    【解决方案2】:

    我拿到数据的时候不知道怎么计算。但我认为你同步/异步获得的任何数据都可以用于计算,它只需要一个回调来告诉控制器我有数据,你需要重置单元格高度。这就是我的想法。

    【讨论】:

      猜你喜欢
      • 2016-02-08
      • 1970-01-01
      • 2013-08-22
      • 2016-12-08
      • 2021-10-12
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      • 2014-02-11
      相关资源
      最近更新 更多