简体   繁体   中英

How to hide a section in UITableView?

There are some section in the table that does not contain any data and would like to hide that section.

How to do this?

Actually, you can "hide" a section. If you want to use a similar behaviour to the built-in contacts app, where sections are hidden but still listed in the index on the right you can do the following:

Implement the UITableViewDataSource protocol:

  • Return all section names (even hidden ones) in - the sectionIndexTitlesForTableView method.

  • For each empty section, return nil from the titleForHeaderInSection method.

  • For each empty section return 0 for the numberOfRowsInSection method.

I find this works better than deleting sections, because the user has consistent index navigation.

You can't "hide" a section as such, but you can "delete" it from the table view using the deleteSections:withRowAnimation: method. This will remove it from the view, with an optional animation, without affecting your backing data. (You should, however, update the data anyway so that the section doesn't reappear.)

More info: UITableView class reference

It is true that 0 is not a valid height for headers and footers. However, the heights are CGFloat values. You can specify a very small number (I've used 0.1) for the height of the section headers and footers.

Kind of a hack, but it works.

I disagree with Tim. We have a way to access any section/row of a table from anywhere in our code and change its .hidden property (and all other properties).

This is the way I usually use:

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:2];
[self.SeymourCakesTableView cellForRowAtIndexPath:indexPath].hidden = YES;

您可以将该部分中的行数设置为0.但是,它会留下一个明显的空白区域。

You can also return the number of records that do contain data from the numberofSectionsInTableView: method and use a switch(indexPath.section) where you let the empty records 'fall through' to the next switch, like:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    switch (indexPath.section) {
        case 0:
            return <header cell>;
            break;

        case 1:
            if(firstRecordHasData){
                return <second cell>;
                break;
            }

        case 2:
            if(secondRecordHasData){
                return <second cell>;
                break;
            }

        case 3:
            return <some other cell>;
            break;

        default:
            return <a regular cell>;
            break;
    }   
}

I was struggling with this for a while because I had to leave out sections in the middle of a grouped table. Tried with setting cell-, header- and footer heights to 0.0 but that didn't work. Couldn't just delete certain sections because of the called methods depending on the selected row. This was going to be a huge if..else if...else if with multiple callings of subroutines. Glad I thought of the good old switch method, maybe it helps you as well :-)

You probably need to remove the section itself from the data backing your table. I don't think there's anything that lets you just hide a section.

You can set the particular section rows height to 0. Also, with the section header if you want. Datasource would still be there, only not showing up.

Section Rows

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) {
        if (_shouldHidden) {
            return 0.0;
        }
        else {
            return 55.0;
        }
    }
    else {
        return 55.0;
    }
}

If you return 0 for the height of the section, Apple API will ignore it. So just return a small value greater than 0.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
  if (section == 0) {
    return 1;
  }

  return 44;
}

Also implement view for header and return nil for the section you don't want to show.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
  if (section == 0 && !self.personaCells.count) {
    return nil;
  }

  UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 44)];
  UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 20, headerView.frame.size.width, 20)];
  NSString *headerTitle = @"SAMPLE TITLE";
  headerLabel.text = headerTitle;    
  [headerView addSubview:headerLabel];
  return headerView;
}

Try like this:-

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    CGFloat headerHeight=10.f;
    if (section==0)
    {
        headerHeight=0.01f;
    }
    else
    {
        headerHeight=50.0f;
    }
    return headerHeight;
}

For the case of static table, that is, the table sections and cells are configured in Storyboard. The following are my strategies to hide a specified section depending conditions.

Step one : implement two func defined in UITableViewDelegate - heightForRowAt - heightForHeaderInSection

For example, here are swift codes:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
{
   // if indexPath contains the specified section AND
   //    the condition for hiding this section is `true`
   //       return CGFloat(0)
   // else 
   //    return super.tableView(tableView, heightForRowAt: indexPath)
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat 
{
   // similar logic to set header height
}

Step two : define a func to set cells hidden for specific section and call it from viewWillAppear:

private func setSectionVisible()
{
   /*
   if condition for visible is true
      let index = IndexPath(row:..., section:...)
      let cell = self.tableView.cellForRow(at: index)
      cell.isHiden = true
   */
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.setSectionVisible()
}

In case you need to reload tableview, you may need to call setSectionVisible() again.

I think this strategy may work for dynamic data from DataSource. In this way, you can control when to make specific section visible or hidden.

For hiding a section, even in the middle of the table view you would need all of the following

#define DEBUG_SECTION 1

#if ! DEBUG_BUILD
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == DEBUG_SECTION)
        return CGFLOAT_MIN;
    return [super tableView:tableView heightForHeaderInSection:section];
}
//------------------------------------------------------------------------------

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (section == DEBUG_SECTION)
        return CGFLOAT_MIN;
    return [super tableView:tableView heightForFooterInSection:section];
}
//------------------------------------------------------------------------------

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == DEBUG_SECTION)
        return nil;
    return [super tableView:tableView titleForHeaderInSection:section];
}
//------------------------------------------------------------------------------

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
    if (section == DEBUG_SECTION)
        return nil;
    return [super tableView:tableView titleForFooterInSection:section];
}
//------------------------------------------------------------------------------

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == DEBUG_SECTION)
        return 0;
    return [super tableView:tableView numberOfRowsInSection:section];
}
//------------------------------------------------------------------------------
#endif // #if ! DEBUG_BUILD

if you left out titleFor/headerFor... you will get some empty rows
if you left out heightFor... the title/footer header text will still appear

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