简体   繁体   中英

UITableView inside UITableViewCell with dynamic cell height

I have a dynamic list of items, each item could have different teamplate/layout (and height). And one those item types could have an internal list of items to select from, regularly 5-6 rows, each has different height.

If I try to describe it further, in my scenario I have one tableview (#slave) inside tableviewcells (#master-cell) of another tableview (#master). Moreover cells (#slave-cell) in my #slave tableview could have different height as well. So I need to layout my #slave to have #master automatically calc and update its size.

在此输入图像描述

I have the issue with the inner table (#slave). In case of auto-layout, to fit all the cell space, the table will be collapsed unlike UILabel or other controls. So what I need here is to get the projected size of #slave table and set the height of the #slave = content height of the #slave.

I found similar post and it works if all rows have the same height but I'm using custom rows with dynamic height so the tableView.contentSize.Height gives me invalid result (basically just multiply rowNumbers * estimatedRowHeight, you can see it on the screenshot, master item #3 has 4 inner cells). Even after calling #slave.reloadData I couldn't get that size.

What is the proper way to build that kind of UI?

Source code with a test project attached (Xamarin.iOS)

I just ran into the same problem a few days ago,and tried to work it around.

The #master-cell works like a childViewController,it's the delegate datasource of the #slave TableViewController.But you cann't have a childViewController in the UITableViewcell.

Customize UITableViewCell to hold necessary property and acts as #slave TableViewController's delegate datasource ,and configure #slave-cell's height and data.

The real problem is the height for #master-cell,

  1. If your data is simple and static,you can compute the height in advance,and return it in method func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat of the ViewController.
  2. Otherwise,add a method to #master-cell which return the height for the whole cell when its property is set.And create a proxy #master-cell to compute the height and return it :

     override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let cell = CustomUITableViewCell(); let model = self.getModel(indexPath) cell.model = model let height = cell.requiredHeight() return height; } 

    It's complex and expensive,but it works.

I think you do not have need of take UITableView inside UITableView . You can take more than one section in UITableView . And use different cellReuseIdentifier. This way your goal will be achieved.

对于这样的布局,ios在tableview中提供了部分,对于主项目使用SectionView(有sectionView的委托方法 - >,你可以在其中提供一个部分的视图),因为不同的部分可能有不同类型的行,所以根据需要创建行并根据部分归还。

Perhaps it is because I do not know the background of you project or what you are trying to accomplish, but tableViews inside of tableVIew cells sounds unnecessarily trivial. Rather than using a master tableView with #slave tableViews, it would be cleaner to just break things out by section in a single tableView as stated in a previous answer. There are UITableViewDelegate methods designed to streamline this for you!

first you have to get string's height then the height have to give in below tableView delegate

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return stringHeight;

}

it is working for me.

I'm using Xcode 8.3.2 and Swift3.1.

I had the same requirement, have tried all, nothing worked for me.

Finally, UIStackView is what worked for me.

In a tableviewcell, I have added a UIStackView(Verticle), keep adding sub cells to that UIStackView. And it automatically increased the cell height.

Check the following to add UIStackView programmatically.

Add views in UIStackView programmatically

If you Use Different Sections and Rows use the below format, its working for me,

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) {
        return 121;
    }
    if(indexPath.section==1)
    {
        return 81;
    }

    if (indexPath.section%2 == 0 && indexPath.row == 1) {
        return 161;
    }

    if (indexPath.section%2 != 0 && indexPath.row == 0) {
        return 81;
    }

    if (indexPath.section==16 && indexPath.row==0) {
        return 161;
    }
    else
    {
        return 44;
    }
}

i have Template code, different section and row, its each row have different sizes, so i have give this type of code, if you get idea see the above code then its helpful for you,

or

If you change the height for Content text size use the below code, its calculate the content size then change the height(UILabel) size, its working for me

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ListModel *model = [ListArray objectAtIndex:indexPath.row];

    CGRect labelRect = [model.content boundingRectWithSize:CGSizeMake(tableView.frame.size.width - 90 - 15, 0)
                        options:NSStringDrawingUsesLineFragmentOrigin
                        attributes:@{
                                     NSFontAttributeName : [UIFont fontWithName:@"Arial" size:14.0]
                                     }
                        context:nil];

    CGFloat heightOfCell = labelRect.size.height + 60;

    if(heightOfCell > 106)
        return heightOfCell;

    return 106;
}

hope its helpful

yes of course you can have as many prototypes cells as you want for example check this piece of code:

     override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if indexPath.section == 0 {

        let cell =  tableView.dequeueReusableCellWithIdentifier("TodayWeatherCell", forIndexPath: indexPath) as! SITodayWeatherTableViewCell

        cell.setupCell(upCommingWeather)
        cell.aboutCityUpdateTableViewClousure = {
            self.tableView.reloadData()
        }

        return cell
    }else {

        let cell = tableView.dequeueReusableCellWithIdentifier("cityDetailCell", forIndexPath: indexPath) as! SICityDetailTableViewCell
        let detail = detailCity[indexPath.row]
        cell.setupCityDetail(detail)

        return cell
        // Configure the cell...
    }
  }

There are two different cells in one single UITableView.

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM