UITableView - 由单元格本身控制的动态单元格高度

发布于 2024-12-21 21:51:27 字数 1119 浏览 2 评论 0原文

我有以下设置:带有自定义 UITableViewCell 实现的 UITableView。在每个单元格中我都有一个 UILabel 和一个 UIButton。当表格首次显示时,在每个单元格中,UILabel 的行数设置为 1,并且所有单元格都具有固定高度(在我的例子中为 60 px)。当点击单元格中的按钮时,UILabel 的行数将设置为 0 并打开自动换行,从而有效地扩展表格单元格。

现在的问题是,只有 UITableViewCell 的实现知道标签是否展开 - 以及单元格的高度应该是多少。然而,所有者文件是表的数据源。

我不知道如何设置它。任何想法表示赞赏。

更新这里是我的代码摘录

在自定义 UITableViewCell 实现中:

- (float)requiredHeight
{
    if(isFull)
    {
        CGSize labelSize = [LblTitle.text sizeWithFont: [LblContent font]
                                     constrainedToSize: CGSizeMake(300.0f, 300.0f) 
                                         lineBreakMode: UILineBreakModeTailTruncation];
        return 42.0f + labelSize.height;
    }
    else
    {
        return 60.0f;
    }
}

在所有者文件(UITableViewDelegate)中:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    OOCommentCell *cell = (OOCommentCell*)[tableView cellForRowAtIndexPath:indexPath];
    return [cell requiredHeight];
}

但是,这会随机导致无限循环或 BAD_ACCESS_EXCEPTION。

I have the following setup: UITableView with custom UITableViewCell implementation. In each cell I have a UILabel and a UIButton. When the table is first displayed, in each of the cells, the UILabel has the number of lines set to 1 and all cells have fixed height (60 px in my case). When the button in the cell is tapped, then the UILabel's number of lines is set to 0 and word wrap is turned on, effectively expanding the table cell.

Now, the issue is that only the implementation of UITableViewCell knows whether the label is expanded or not - and thus what the cell height should be. However the owner file is the table's datasource.

I can't get may head around how to set this up. Any ideas are appreciated.

Update here are extracts from my code

In the custom UITableViewCell implementation:

- (float)requiredHeight
{
    if(isFull)
    {
        CGSize labelSize = [LblTitle.text sizeWithFont: [LblContent font]
                                     constrainedToSize: CGSizeMake(300.0f, 300.0f) 
                                         lineBreakMode: UILineBreakModeTailTruncation];
        return 42.0f + labelSize.height;
    }
    else
    {
        return 60.0f;
    }
}

In owner file (UITableViewDelegate):

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    OOCommentCell *cell = (OOCommentCell*)[tableView cellForRowAtIndexPath:indexPath];
    return [cell requiredHeight];
}

However this results randomly in an infinite loop or in BAD_ACCESS_EXCEPTION.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羞稚 2024-12-28 21:51:27

好吧,经过一番挣扎,这就是我最终得到的结果,这是有效的。

  1. 我创建了一个简单的类来包含与一个单元格相关的信息:
@interface CommentInfo : NSObject
{
    整数ID;
    NSString *名称;
    NSString *日期;
    NSString *内容;
    BOOL 已满;
    浮动高度;
}

@property(只读)int ID;
@property (只读) NSString *名称;
@property (只读) NSString *Date;
@property (只读) NSString *Content;
@property(读写,分配)浮动高度;
@property (读写, 分配) BOOL IsFull;

- (id)initWithID:(int)_id withName:(NSString *)_name withDate:(NSString *)_date withText:(NSString *)_text;

@结尾

不要太担心所有属性 - 最重要的是 Height

  1. 在我的控制器(也是表视图的委托)中,我将数据保存为指向 CommentInfo 类型对象的指针的 NSMutableArray

  2. cellForRowAtIndexPath 中,我获取相应的指针,并在构造期间将其传递给自定义单元实现,并将其存储在此处。我还将 self 设置为单元格的委托。

  3. 在自定义单元格实现中,当我需要扩展/更改高度时,我会更新 CommentInfo 对象中的 Height 属性,并调用委托中的方法来更新显示。

  4. 当调用这个 updateDisplay 方法时,我简单地执行以下操作:

[CommentsTable beginUpdates];
[评论表结束更新];
  1. heightForRowAtIndexPath 方法中,我检索相应的 CommentInfo 指针并读取 Height 属性。由于控制器和单元之间的指针相同,因此对此属性的任何更改都将在两个类中可见。

工作完成了。

OK, after some struggling, here's what I ended up with, which kind of works.

  1. I created a simple class to contain information related to one cell:
@interface CommentInfo : NSObject
{
    int ID;
    NSString *Name;
    NSString *Date;
    NSString *Content;
    BOOL IsFull;
    float Height;
}

@property (readonly) int ID;
@property (readonly) NSString *Name;
@property (readonly) NSString *Date;
@property (readonly) NSString *Content;
@property (readwrite, assign) float Height;
@property (readwrite, assign) BOOL IsFull;

- (id)initWithID:(int)_id withName:(NSString *)_name withDate:(NSString *)_date withText:(NSString *)_text;

@end

Don't worry too much about all the properties - the most important one is the Height.

  1. In my controller (which is also the delegate for the table view), I keep the data as an NSMutableArray of pointers to objects of type CommentInfo.

  2. In cellForRowAtIndexPath I get the corresponding pointer and pass it to the custom cell implementation during construction, where it is stored. I also set self as a delegate to the cell.

  3. In the custom cell implementation, when I need to expand/change the height, I update the Height property in the CommentInfo object and call a method in the delegate to update the display.

  4. When this updateDisplay method is called, I simple do the following:

[CommentsTable beginUpdates];
[CommentsTable endUpdates];
  1. In heightForRowAtIndexPath method, I retrieve the corresponding pointer to CommentInfo and read the Height property. As the pointer is the same between the controller and the cell, any changes to this property will be visible in both classes.

Job done.

山色无中 2024-12-28 21:51:27

实现方法 UITableViewDelegate – tableView:heightForRowAtIndexPath: 在你的表委托中。如果您想在每个单元格的基础上定义高度,您可以通过在 tableView:heightForRowAtIndexPath 中调用您自己的 tableView:cellForRowAtIndexPath: 方法,将此调用“转发”到单元格的类。

更新:用代码实现。该错误是由调用 tableView:cellForRowAtIndexPath 的委托中不正确的方法签名引起的。

在自定义 UITableViewCell 实现中:

- (CGFloat)requiredHeight
{
    if(isFull)
    {
        CGSize labelSize = [LblTitle.text sizeWithFont: [LblContent font]
                                     constrainedToSize: CGSizeMake(300.0f, 300.0f) 
                                         lineBreakMode: UILineBreakModeTailTruncation];
        return 42.0f + labelSize.height;
    }
    else
    {
        return 60.0f;
    }
}

在所有者文件 (UITableViewDelegate) 中:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    OOCommentCell *cell = (OOCommentCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];
    return [cell requiredHeight];
}

Implement the method UITableViewDelegate – tableView:heightForRowAtIndexPath: in your table delegate. If you want to define height on a per-cell basis, you could 'forward' this call to the cell's class by calling your own tableView:cellForRowAtIndexPath: method in tableView:heightForRowAtIndexPath.

Update: Implemented in code. The error was caused by an incorrect method signature in the delegate calling tableView:cellForRowAtIndexPath.

In the custom UITableViewCell implementation:

- (CGFloat)requiredHeight
{
    if(isFull)
    {
        CGSize labelSize = [LblTitle.text sizeWithFont: [LblContent font]
                                     constrainedToSize: CGSizeMake(300.0f, 300.0f) 
                                         lineBreakMode: UILineBreakModeTailTruncation];
        return 42.0f + labelSize.height;
    }
    else
    {
        return 60.0f;
    }
}

In owner file (UITableViewDelegate):

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    OOCommentCell *cell = (OOCommentCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];
    return [cell requiredHeight];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文