UITableView: hide header from empty section

落爺英雄遲暮 提交于 2019-12-17 21:43:11

问题


i have a UITableView, that displays expenses from a current month (see screenshot):

My problem is with the header for empty sections. is there any way to hide them? The data is loaded from coredata.

this is the code that generates the header title:

TitleForHeader

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
    return nil;
} else {

NSDate *today = [NSDate date ];
int todayInt = [dataHandler getDayNumber:today].intValue;

NSDate *date = [NSDate dateWithTimeIntervalSinceNow:(-(todayInt-section-1)*60*60*24)];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[NSLocale preferredLanguages] objectAtIndex:0]]];    
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
    return formattedDateString;}

}

ViewForHeader

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
    return nil;
} else {

    UIView *headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 312, 30)];
    UILabel *title = [[UILabel alloc]initWithFrame:CGRectMake(4, 9, 312, 20)];
    UIView *top = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 312, 5)];
    UIView *bottom = [[UIView alloc]initWithFrame:CGRectMake(0, 5, 312, 1)];

    [top setBackgroundColor:[UIColor lightGrayColor]];
    [bottom setBackgroundColor:[UIColor lightGrayColor]];

    [title setText:[expenseTable.dataSource tableView:tableView titleForHeaderInSection:section]];
    [title setTextColor:[UIColor darkGrayColor]];
    UIFont *fontName = [UIFont fontWithName:@"Cochin-Bold" size:15.0];
    [title setFont:fontName];


    [headerView addSubview:title];
    [headerView addSubview:top];
    [headerView addSubview:bottom];

    return headerView;

}

}

heightForHeader

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {

NSLog(@"Height: %d",[tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0);
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section == 0]) {
    return 0;
} else {
    return 30;
}
}

numberOfRowsInSection

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {

int rows = 0;
for (Expense* exp in [dataHandler allMonthExpenses]) {
    if ([exp day].intValue == section) {
        rows++;
    }
}

return rows;
}

sebastian

回答1:


What if in – tableView:viewForHeaderInSection: you return nil if the section count is 0.

EDIT : You can use numberOfRowsInSection for obtaining the number of elements in the section.

EDIT: Probably you should return nil also in titleForHeaderInSection if numberOfRowsInSection is 0.

EDIT: Did you implement the following method?

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

EDIT : Swift 3 example

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch section {
    case 0:
        if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
            return "Title example for section 1"
        }
    case 1:
        if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
            return "Title example for section 2"
        }
    default:
        return nil // when return nil no header will be shown
    }
    return nil
}



回答2:


You have to set tableView:heightForHeaderInSection: to 0 for the appropriate sections. This is something which changed fairly recently and got me in a couple places. From UITableViewDelegate it says...

Prior to iOS 5.0, table views would automatically resize the heights of headers to 0 for sections where tableView:viewForHeaderInSection: returned a nil view. In iOS 5.0 and later, you must return the actual height for each section header in this method.

So you'll have to do something like

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return 0;
    } else {
        // whatever height you'd want for a real section header
    }
}



回答3:


In my strange situation I have to return:

viewForHeaderInSection -> nil

viewForFooterInSection -> nil (don't forget about footer!)

heightForHeaderInSection -> 0.01 (not zero!)

heightForFooterInSection -> 0.01

only in this case empty sections disappear completely




回答4:


Take a look at the method -[UITableViewDelegate tableView:heightForHeaderInSection:]. Especially the note that accompanies its documentation:

Prior to iOS 5.0, table views would automatically resize the heights of headers to 0 for sections where tableView:viewForHeaderInSection: returned a nil view. In iOS 5.0 and later, you must return the actual height for each section header in this method.




回答5:


I know this is an old question but I'd like to add to it. I prefer the approach of setting the titleHeader to nil over altering the heightForHeaderInSection to 0 as it can cause problems with indexPath being +1 from where is should be due to the header still being there but hidden.

So with that said and building on DBD's answer you can set the titleForHeaderInSection: to nil for sections with no rows in it like so:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    } else {
        // return your normal return
    }
}



回答6:


In 2015 using iOS 8 and Xcode 6, the following worked for me:

/* Return the title for each section if and only if the row count for each section is not 0. */

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    }else{

    // here you want to return the title or whatever string you want to return for the section you want to display

    return (SomeObject*)someobjectArray[section].title;
    }
}



回答7:


This seems to be the proper way, It will animate correctly & works clean... as Apple intended...

Provide appropriate info to the tableView delegate

When no items in section, Return 0.0f in:

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

..Also return nil for:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

Do appropriate data removal for tableView

  1. Call [tableView beginUpdates];
  2. Remove items from your dataSource, keeping track of where elements got removed..
  3. Call deleteRowsAtIndexPaths with the indexPaths of the cells you removed.
  4. if your datasource has no items in it (Here you would end up with just the header). Call reloadSections: to reload that section. This will trigger the correct animation and hide/slide/fade the header.
  5. Finally call [tableView endUpdates]; to finish the update..



回答8:


Swift 4.2

Set the heightForHeaderInSection to Zero and if you've a custom section view, set it to nil for sections without cells.

func tableView(_ tableView: UITableView,
                   heightForHeaderInSection section: Int) -> CGFloat {
        return height_DefaultSection
    }

func tableView(_ tableView: UITableView,
                   viewForHeaderInSection section: Int) -> UIView? {

        return tableView.dataSource?.tableView(tableView, numberOfRowsInSection: section) == 0 ? nil: headerView(tableView: tableView, section: section)
    }


来源:https://stackoverflow.com/questions/9737616/uitableview-hide-header-from-empty-section

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!