UITableViewCell

时间:2016-09-22 01:13:49

标签: ios objective-c iphone uitableview uicollectionview

我的应用中已有一个已存在的表视图,我试图添加一个新的单元格。新单元格将显示可变数量的按钮,每个按钮都有一个标题(因此是动态宽度)。新单元应该看起来像这样:

┃┃                                   ┃┃  <---- existing cells above
┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃
┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃
┃┃┏━━━━━┓  ┏━━━━━━━━━━━━━━━━━━━┓     ┃┃
┃┃┃ 632 ┃  ┃ 12345678901728933 ┃     ┃┃
┃┃┗━━━━━┛  ┗━━━━━━━━━━━━━━━━━━━┛     ┃┃
┃┃┏━━━━━━━━━━━┓  ┏━━━━━━┓  ┏━━━━━━┓  ┃┃
┃┃┃ 123345573 ┃  ┃ jhkl ┃  ┃ dasd ┃  ┃┃  <---- new cell
┃┃┗━━━━━━━━━━━┛  ┗━━━━━━┛  ┗━━━━━━┛  ┃┃
┃┃┏━━━┓  ┏━━━━━━━━━━━━━━┓  ┏━━━┓     ┃┃
┃┃┃ 1 ┃  ┃ 128732434554 ┃  ┃ 1 ┃     ┃┃
┃┃┗━━━┛  ┗━━━━━━━━━━━━━━┛  ┗━━━┛     ┃┃
┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃
┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃
┃┃                                   ┃┃  <---- existing cells below

按钮应该在一行上文件,直到下一行按钮溢出单元格,此时它应该换行到下一行(类似于带有自动换行的UILabel)。

重要注意事项

  1. 此单元格需要具有动态高度。我从UITableViewAutomaticDimension方法返回tableView:heightForRowAtIndexPath,单元格需要计算自己的高度。
  2. 按钮标题数据将在从cellForRowAtIndexPath返回单元格之前填充
  3. 我试图找到一个不需要在表格视图上调用beginUpdates/endUpdates来调整其单元格大小的解决方案。
  4. 我更喜欢使用Autolayout这样做,但我愿意手动计算帧,如果我真的需要(虽然我不完全确定如何做到这一点,所以可能需要一些指导)。
  5. 此视图也需要在表格视图单元格的中使用,因此我无法查看[UIScreen mainScreen]来计算单元格的理想宽度。< / LI>

    我已经尝试过了

    1. 我尝试使用UICollectionView实现视图。在这种情况下,集合视图的数据源返回包含在UICollectionViewCells中的按钮。这个问题是UICollectionView是一个UIScrollView,因此不会自动调整自身大小以适应其内容。
    2. 我尝试使用自定义UICollectionView子类,其自定义实现为intrinsicContentSize。此实现将返回集合视图的contentSize,或集合视图的UICollectionViewFlowLayout的collectionViewContentSize()(我尝试了两者)。这里的问题是这些值在设置collectionView之前不会返回实际的内容大小,此时我的UITableView已经将单元格高度缓存为0。
    3. 我尝试使用UICollectionView并保持NSLayoutConstraint的高度,每次contentSize更改时都会更改。不幸的是,这与上面的问题相同,因为UITableView在更改contentSize之前布局了单元格。
    4. 我尝试使用嵌套的UIStackViews实现完全自定义的单元格:在这种情况下,我将在单元格内部有N个水平堆栈视图。我会在第一个堆栈视图中添加按钮,直到它们的总宽度超过单元格的边界,此时我会将它们添加到下一个堆栈视图中,等等。问题是为了做到这一点,我需要要知道单元格的边界,这些边界在调用layoutSubviews之前没有设置,此时UITableView已经缓存了单元格的高度。
    5. 我尝试使用类似https://github.com/xhacker/TagListView的内容,其中自定义视图在调用layoutSubviews时手动计算所有内容的帧并报告(行数)*(每行的高度)作为其内在内容高度,但问题是,当计算发生时,视图的帧为0(因为它被布置在UITableViewCell内),因此内在内容大小计算错误,结果在这样的事情:

      ┃┃                                   ┃┃  <---- existing cells above
      ┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃
      ┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃
      ┃┃┏━━━━━┓   ┏━━━━━━━━━━━━┓           ┃┃
      ┃┃┃ 632 ┃   ┃ 6327237842 ┃           ┃┃
      ┃┃┗━━━━━┛   ┗━━━━━━━━━━━━┛           ┃┃
      ┃┃┏━━━━━━━━━━━━━━━━━━━┓              ┃┃
      ┃┃┃ 12345678901728933 ┃              ┃┃
      ┃┃┗━━━━━━━━━━━━━━━━━━━┛              ┃┃    
      ┃┃                                   ┃┃
      ┃┃                                   ┃┃  <---- new cell
      ┃┃                                   ┃┃
      ┃┃                                   ┃┃
      ┃┃                                   ┃┃
      ┃┃                                   ┃┃
      ┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃
      ┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃
      ┃┃                                   ┃┃  <---- existing cells below
      
    6. 通常,UITableView缓存单元格的高度会导致存在一个名为UIView-Encapsulated-Layout-Height的约束,其常量为0,并在许多SO帖子中有详细记录。据我所知,无法从单元格级别重新计算此高度:setNeedsUpdateConstraintssetNeedsLayoutlayoutIfNeededinvalidateIntrinsicContentSize和任何我试过的组合没有帮助。

      过去两天,这让我很困惑。我想知道是否有人之前已经实现了这样的任何事情并找到了一个可靠的方法,或者可以就如何解决这个问题提供任何建议。

1 个答案:

答案 0 :(得分:-1)

将此写入表cellforRowAtIndexPath方法。

        y=20;
        x=20;

        for (int i=0; i<[arrAssignUsers count]; i++) {
            CGRect screenRect=[[UIScreen mainScreen]bounds];
            CGFloat screenWidth=screenRect.size.width;


            [arrBtnStatus addObject:[NSNumber  numberWithBool:NO]];

            NSString *strNames=[arrAssignUsers objectAtIndex:i];
            stringsize=[strNames sizeWithAttributes:
                        @{NSFontAttributeName: [UIFont systemFontOfSize:20.0f]}];
            btn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
            CGFloat m=x+stringsize.width+10;
            CGFloat n=screenWidth-20;

            if (m<=n) {
                btn.frame=CGRectMake(x, y,stringsize.width,stringsize.height);
                x=x+stringsize.width +10;
            }
            else
            {
                y=y+stringsize.height+10;
                x=20;
                btn.frame=CGRectMake(x, y,stringsize.width,stringsize.height);
                x=x+stringsize.width+10;
            }

            [btn setTitle:self.arrAssignUsers[i] forState:UIControlStateNormal];
            [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            btn.tag=i;
            [btn addTarget:self
                    action:@selector(notifyButtonPressedInEditTask:) forControlEvents:UIControlEventTouchUpInside];

            btn.backgroundColor=[UIColor whiteColor];
            btn.layer.cornerRadius=10;
            [btn.layer setMasksToBounds:YES];
            btn.layer.borderWidth=2.0f;
            btn.layer.borderColor=[UIColor orangeColor].CGColor;

            [self checkNotifybtnStatus:btn];
            [cell addSubview:btn];
            return cell;

然后写下这个方法:

-(void)checkNotifybtnStatus:(UIButton *)clicked{
state = [[arrBtnStatus objectAtIndex:clicked.tag]boolValue];

if ((clicked.tag>=0)&&(state==YES)) {
    clicked.backgroundColor=OS_ORANGE_COLOR;
}
else
    clicked.backgroundColor=[UIColor clearColor];
}

然后写下来。

-(void)notifyButtonPressedInEditTask:(id)sender{
UIButton *clicked = (UIButton *) sender;
NSLog(@"%ld",(long)clicked.tag);    //Here you know which button has pressed


for (UserListData *taskData in arrAssignUserInfoList) {
    [arrNotifyUsers addObject:taskData.strUniqID];
}

 state = [[arrBtnStatus objectAtIndex:clicked.tag]boolValue];

if ((clicked.tag>=0)&&(state==NO)) {
    [arrBtnStatus replaceObjectAtIndex:clicked.tag withObject:[NSNumber numberWithBool:!state]];
    clicked.backgroundColor=[UIColor colorWithRed:254.0/255.0 green:139.0/255.0 blue:26.0/255.0 alpha:1];

    [arrNotifySelectedUsers addObject:[arrNotifyUsers objectAtIndex:clicked.tag]];
    NSLog(@" arr new--%@",arrNotifySelectedUsers.description);
}
else
{
    clicked.backgroundColor=[UIColor clearColor];
    [arrBtnStatus replaceObjectAtIndex:clicked.tag withObject:[NSNumber numberWithBool:!state]];
    [arrNotifySelectedUsers removeObject:[arrNotifyUsers objectAtIndex:clicked.tag]];
    NSLog(@" arr new--%@",arrNotifySelectedUsers.description);
}
}

根据您的项目更改变量。 这可能会对你有所帮助。