developer tip

UITableView : 빈 섹션에서 헤더 숨기기

optionbox 2020. 10. 25. 12:08
반응형

UITableView : 빈 섹션에서 헤더 숨기기


이번 달의 비용을 표시하는 UITableView가 있습니다 (스크린 샷 참조).

내 문제는 빈 섹션의 헤더에 있습니다. 숨길 방법이 있나요? 데이터는 coredata에서로드됩니다.

다음은 헤더 제목을 생성하는 코드입니다.

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;
}

여기에 이미지 설명 입력 세바스찬


만약에 – 섹션 수가 0이면 tableView:viewForHeaderInSection:당신 return nil.

편집 : numberOfRowsInSection섹션의 요소 수를 얻는 데 사용할 수 있습니다 .

편집 : 아마도 0 titleForHeaderInSection이면 nil을 반환해야합니다 numberOfRowsInSection.

편집 : 다음 방법을 구현 했습니까?

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

편집 : Swift 3 예제

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
}

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
    }
}

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


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.


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
    }
}

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;
    }
}

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..

Swift 4.2

heightForHeaderInSection을 0으로 설정하고 사용자 정의 단면도가있는 경우 셀이없는 섹션에 대해 nil로 설정하십시오.

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)
    }

참고 URL : https://stackoverflow.com/questions/9737616/uitableview-hide-header-from-empty-section

반응형