【问题标题】:UITableViewCell with subviews is not working properly带有子视图的 UITableViewCell 无法正常工作
【发布时间】:2014-06-11 15:45:43
【问题描述】:

我的 iOS 应用程序中有 UITableView,我想向单元格添加一些子视图。我使用

[cell.contentView addSubview:someView];

而且效果很好,但是...当我向下滚动时,子视图开始隐藏在顶部的单元格中,当我滚动回顶部时,它们不会再次出现...我做错了什么?请问有什么解决办法吗?

编辑

我主要说的是“detailtext”标签,但在更多情况下我会遇到这些问题......

这是完整的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell;

switch (indexPath.row) {
    case 0:
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        break;

    default:
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        break;
}


UIView *separatorLine = [[UIView alloc] init];

separatorLine.frame = CGRectMake(15.0f, 60 - 0.5f, cell.frame.size.width-15.0f, 0.5f);
separatorLine.tag = 4;
separatorLine.backgroundColor = [UIColor lightGrayColor];

cell.layer.masksToBounds = NO;

tableView.backgroundColor = [UIColor colorWithRed:33.0 / 255.0 green:157.0 / 255.0 blue:147.0 / 255.0 alpha:1.0];

cell.selectionStyle = UITableViewCellSelectionStyleNone;

UIView *row2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];

UIView *profileBorder = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-50, 50, 102, 102)];

profileBorder.layer.borderColor = [UIColor whiteColor].CGColor;
profileBorder.layer.borderWidth = 5; //2
profileBorder.layer.cornerRadius = 50;


NZCircularImageView *profileImage = [[NZCircularImageView alloc] initWithFrame:CGRectMake(1,1, 100, 100)];
profileImage.image = profilePhoto;
profileImage.contentMode = UIViewContentModeScaleAspectFill;

UITapGestureRecognizer *showBigProfilePhoto = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showImage:)];

profileImage.userInteractionEnabled = YES;
[profileImage addGestureRecognizer:showBigProfilePhoto];

[profileBorder addSubview:profileImage];

UILabel *numberFeelings = [[UILabel alloc] initWithFrame:CGRectMake(10, 100-25, 100, 50)];

numberFeelings.text = [NSString stringWithFormat:@"%@\nFeelings", feelings];
numberFeelings.font = [UIFont boldSystemFontOfSize:16];
numberFeelings.textAlignment = NSTextAlignmentCenter;
numberFeelings.textColor = [UIColor whiteColor];
numberFeelings.numberOfLines = 0;

UILabel *numberFriends = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2+60, 100-25, 100, 50)];

numberFriends.text = [NSString stringWithFormat:@"%@\nFollowers", friends];
numberFriends.font = [UIFont boldSystemFontOfSize:16];
numberFriends.textColor = [UIColor whiteColor];
numberFriends.numberOfLines = 0;
numberFriends.textAlignment = NSTextAlignmentCenter;

[row2 addSubview:profileBorder];
[row2 addSubview:numberFriends];
[row2 addSubview:numberFeelings];

int rectButtons = cell.frame.size.width-246;

UIImageView *graph = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2, -20, 82, 82)];
UIImageView *badgets = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+82, -20, 82, 82)];
UIImageView *photos = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+164, -20, 82, 82)];

graph.image = [UIImage imageNamed:@"graph.jpg"];
badgets.image = [UIImage imageNamed:@"badgets.jpg"];
photos.image = [UIImage imageNamed:@"photos.jpg"];

graph.userInteractionEnabled = YES;
badgets.userInteractionEnabled = YES;
photos.userInteractionEnabled = YES;

UITapGestureRecognizer *graphTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showGraph:)];

[graph addGestureRecognizer:graphTap];

NSArray *jmenoCasti = [name componentsSeparatedByString:@" "];

krestni = [jmenoCasti objectAtIndex:0];

int indexOfPost = indexPath.row-3;

NSMutableAttributedString *str;
int countFeeling;
int countString;
int countBeforeFeeling;

if (indexPath.row >=3) {

    str = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ was %@", krestni, [naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:@"_feel"] integerValue]]]];

    countFeeling = [[naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:@"_feel"] integerValue]] length];

    countString = krestni.length+5+countFeeling;

    countBeforeFeeling = countString-countFeeling+1;

    int rangeStart = countBeforeFeeling-1;
    int rangeStop = str.length-rangeStart;

    NSLog(@"%i ... %i", countBeforeFeeling-1, countString-1);

    [str addAttribute:NSFontAttributeName value: [UIFont fontWithName:@"Helvetica-Bold" size:16.0f] range:NSMakeRange(rangeStart, rangeStop)];
    [str addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:32.0 / 255.0 green:147.0 / 255.0 blue:138.0 / 255.0 alpha:1.0] range:NSMakeRange(rangeStart, rangeStop)];

}

UILabel *mainText = [[UILabel alloc] initWithFrame:CGRectMake(15, 70, cell.frame.size.width-10, 20)];
mainText.attributedText = str;

UILabel *detailText;

if (!detailText) {
    detailText = [[UILabel alloc] initWithFrame:CGRectMake(15, 90, cell.frame.size.width-10, 30)];
}
detailText.textColor = [UIColor grayColor];
detailText.font = [UIFont systemFontOfSize:13];

switch (indexPath.row) {
    case 0:
        cell.textLabel.textAlignment = NSTextAlignmentCenter;
        cell.textLabel.text = name;
        cell.textLabel.textColor = [UIColor whiteColor];
        cell.textLabel.font = [UIFont systemFontOfSize:20];
        cell.backgroundColor = [UIColor clearColor];
        break;

    case 1:
        [cell.contentView addSubview:row2];
        cell.backgroundColor = [UIColor clearColor];
        break;

    case 2:
        cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
        [cell.contentView addSubview:graph];
        [cell.contentView addSubview:badgets];
        [cell.contentView addSubview:photos];
        break;

    default:
        detailText.text = [[posts objectAtIndex:indexPath.row-3] objectForKey:@"_text"];
        [cell.contentView addSubview:detailText];
        cell.textLabel.attributedText = str;
        cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
        break;
}


return cell; }

【问题讨论】:

  • 发布添加子视图的整个方法。
  • 为什么不使用 BOOL 属性来跟踪所有添加的子视图。这会奏效。
  • 你能说更多吗?如果可能的话,举个例子......谢谢:-)

标签: ios objective-c uitableview


【解决方案1】:

在您的 tableView:cellForRowAtIndexPath: 中,当您不希望显示信息时,您会隐藏它,但对于应该显示的单元格,您不会显式取消隐藏它。

查看该方法中的前两行:您正确的做法是重用单元格,因此当单元格滚动出视图时,它们会从 UITableView 中移除并放入重用队列中。然后,当单元格应该变得可见时,TableView 会从该队列中获取单元格 - 如果没有可用的单元格,则创建新的单元格。

这一切都很顺利,但过了一会儿,带有隐藏信息按钮的单元格被放入队列中。然后,一段时间后,这些单元格被重用 - 有时用于应该有可见信息的行。

对此有两种解决方案:您可以显式取消隐藏要显示的那些行的信息,也可以使用两种不同类型的单元格,一种具有隐藏信息,另一种具有可见信息。然后,您为每个单元格指定不同的标识符,并根据单元格所在的行,在出列/创建单元格之前设置标识符。

【讨论】:

  • 在他的示例中,他实际上并没有将任何代码出队,是吗?看起来他总是在新牢房里。
【解决方案2】:

您应该为每个不同的单元格创建一个 UITableViewCell 的子类,并将所有不会因数据而改变的视图相关代码添加到初始化方法中。然后在每个单元格中创建一个名为 configureWithData 的方法,并传入与单元格相关的数据。在此配置方法中可以创建属性字符串和修改标签框架。

它将显着减少 UITableViewController 中的混乱,并且在设计方面更加明智。您的视图控制器实际上不需要知道您的表格单元格是什么样的。

这是我所说的一个例子:

-(void)awakeFromNib { 如果(self.accessoryType == UITableViewCellAccessoryDisclosureIndicator) { DTCustomColoredAccessory *accessory = [DTCustomColoredAccessory accessoryWithColor:[UIColor whiteColor]]; 附件.highlightedColor = [UIColor blackColor]; self.accessoryView = 附件; } } -(void)configureCellWithObject:(id)inObject { TableDataModel *dataObject = (TableDataModel *)inObject; self.titleLabel.text = dataObject.titleString; self.subtitleLabel.text = dataObject.subtitleString; self.accessibilityIdentifier = dataObject.accessIdString; 如果(dataObject.imageUrlString != 无) { UIImage *iconImage = [UIImage imageNamed:dataObject.imageUrlString]; 如果(图标图像!= 无) { NSInteger yOffset = [StaticTools centerYOffset:self.frame.size objectFrameSize:iconImage.size]; self.iconImageView.image = iconImage; CGRect 框架 = self.iconImageView.frame; frame.origin.y = yOffset; frame.size = iconImage.size; [self.iconImageView setFrame:frame]; } 别的 { [self.iconImageView loadImageFromUrl:dataObject.imageUrlString]; } } }

【讨论】:

    【解决方案3】:

    这是一种对我有用的简单方法:

    for(UIView *subview in cell.contentView.subviews)
    {
        if([subview isKindOfClass: [UIView class]])
        {
            [subview removeFromSuperview];
        }
    }
    

    你可以在开头使用它

    • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    【讨论】:

    • 这很糟糕。您不希望每次调用 cellForRowAtIndexPath 时都必须遍历单元格内容视图的子视图。虽然它可能有效,但有可能导致性能问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多