【问题标题】:How do you reposition subviews in a UITableViewCell?如何在 UITableViewCell 中重新定位子视图?
【发布时间】:2009-07-03 08:37:26
【问题描述】:

我正在编写一个线程化的 UITableView,它可以从网上检索一些信息。我想在加载图像时显示一个活动指示器来代替常规的 cell.image。

问题在于自定义标签和活动指示器的行为不正常。标签从正确的位置开始,活动指示器显示在正确的位置并开始动画,但是一旦在图像下载线程上遇到第一个回调(基本上只加载一个图像),视图全部就像只有一个参考一样重置,我正在重置所有这些的框架......

我已经重载了 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

有问题的代码在这里:

// Set up the cell...
    if( ![[cell contentView] viewWithTag:indexPath.row+200] ){
        UILabel *newLabel = [[UILabel alloc] init];
        newLabel.text = [[personList objectAtIndex:indexPath.row] name];
        newLabel.frame = [[cell contentView] frame];
        [[cell contentView] addSubview:newLabel];
        newLabel.tag = indexPath.row+200;
        [newLabel release];
    }
    else{
        UILabel *alreadySetLabel = (UILabel *)[[cell contentView] viewWithTag:indexPath.row+200];
        alreadySetLabel.text = [[personList objectAtIndex:indexPath.row] name];
        alreadySetLabel.frame = [[cell contentView] frame];
    }

    UIImageView *tmpImageView = cell.imageView;

    NSLog( @"In cell name: %@", [[personList objectAtIndex:indexPath.row] name] );
    NSLog( @"In cell profile image: %@", [[personList objectAtIndex:indexPath.row] profileImage] );

    if( [[personList objectAtIndex:indexPath.row] profileImage] ){
        tmpImageView.image = [[personList objectAtIndex:indexPath.row] profileImage];
        [[[cell contentView] viewWithTag:indexPath.row+100] removeFromSuperview];
        UILabel *labelRef1 = (UILabel *)[[cell contentView] viewWithTag:indexPath.row+200];
        [labelRef1 setFrame:CGRectMake( cell.contentView.frame.origin.x+70, cell.contentView.frame.origin.y, labelRef1.frame.size.width, labelRef1.frame.size.height)];
    }
    else{
        NSLog( @"%@", [[personList objectAtIndex:indexPath.row] imageFilePath] );
        if( ![[cell contentView] viewWithTag:indexPath.row+100] && [[personList objectAtIndex:indexPath.row] imageFilePath] ){
            UIActivityIndicatorView *newSpin = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            [newSpin setTag:indexPath.row+100];
            [newSpin startAnimating];
            [newSpin setFrame:CGRectMake( 5, ((cell.contentView.frame.size.height/2)-7), 30, ((cell.contentView.frame.size.height/2)-7)+15) ];
            [[cell contentView] addSubview:newSpin];
            [newSpin release];
            UILabel *labelRef2 = (UILabel *)[cell viewWithTag:indexPath.row+200];
            [labelRef2 setFrame:CGRectMake( cell.contentView.frame.origin.x+70, cell.contentView.frame.origin.y, labelRef2.frame.size.width, labelRef2.frame.size.height)];
        }
    }

iPhone 应用程序开发的新手,不到两周。我想知道我是否误解了标签的使用?在我看来,如果您可以将标签值链接到 indexPath,您可以想出唯一标识符来引用自定义视图? 100 和 200 是任意值,这样我就不会意外地在一屏数据中重复使用标签——不知道是否有必要,因为我认为标签只在子视图中搜索。

提前感谢您的任何建议。还可以接受有关如何使其更优雅的一般提示...

谢谢, 乔什

【问题讨论】:

    标签: iphone uitableview


    【解决方案1】:

    我不确定您所说的“视图全部重置,就好像只有一个参考,我正在重置所有视图的框架”,但让我指出一些事情。一般使用标签和加载表格视图单元格图像。

    标签只是在一个视图中识别/检索子视图的一种方式 - 它们不必是全局唯一的。实际上,在标签值中加入indexPath.row 根本不是一个好主意,因为表格视图单元格会重用(只要你使用dequeueReusableCellWithIdentifier:,你肯定应该这样做)。此外,我会将标记值定义为常量(例如#define),并且只在您的代码中引用这些常量。这样,您的代码更具描述性、不易出错且更易于维护。

    说实话,我根本不喜欢使用标签。实际上,在tableView:cellForRowAtIndexPath: 中“即时”构建表格视图单元格是我遇到的唯一没有其他选择的场景(因为您没有任何命名的插座)。我建议您将UITableViewCell 子类化,而不是乱用标签。这真的没什么大不了的,但是您的代码会更简洁,并且您可以轻松地将所有与单元格相关的内容封装在该类中 - 当您执行更复杂的事情(例如通过网络异步加载表格视图单元格图像)时,这一点尤其重要。

    关于异步图片加载的东西,你看过this project on github吗?它基本上是一个演示项目,用于演示如何异步加载(flickr)图像并在完成加载后在表格视图中更新它们 - 不是一个完美的实现,但至少是一个很好的起点。我最近做了同样的事情,但我的方法是子类UIImageView 并在这个子类中执行所有异步加载/更新。主要原因是我想要一个通用且可重用的解决方案。

    【讨论】:

      【解决方案2】:

      你是对的——对单元进行子类化将是封装和大量代码的方法。我必须改变它。

      顺便说一句,我用一个额外的代码分支解决了这个问题。

      为了澄清,问题是我添加到子视图的自定义标签在每次表重新加载数据时都会重置其框架。您会注意到我将其移动了 70 像素以上,以便为活动指示器或已加载的图像留出空间。它会在第一次通过时执行此操作,然后每次在后台线程上加载另一张图片返回时重置为 origin.x = 0。

      显然,标签框无论如何都会被重置?我的代码会在单元格 contentView 中检测到标签为 100 的子视图(我按照您的建议将其更改为静态值,就像我之前所做的那样),并且什么都不做,因为我的印象是矩形会保持静态只要因为视图存在。情况并非如此,无论它是否已经存在,我都必须明确设置框架。无论如何,可能只是我不完全理解引擎盖下发生的事情。一旦我在 else 中添加了一个额外的 setFrame,一切正常。

      谢谢, 乔什

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多