UITableView Custom Section Header, duplicate issue

戏子无情 提交于 2019-12-22 05:27:17

问题


I am having trouble animating a custom UITableView section header.
The goal was to create collapsable sections.
When I tap on the custom header the first time it animates as expected, however every time after that it leaves a duplicate in the original location and animates another.

Image Example:


My Custom Header:

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
       UIView* customView = [[[UIView alloc]initWithFrame:CGRectMake(10.0, 0.0, 300.0, 44.0)]autorelease];
       customView.backgroundColor = [UIColor lightGrayColor];

       UILabel * headerLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
            headerLabel.backgroundColor = [UIColor clearColor];
            headerLabel.opaque = NO;
            headerLabel.textColor = [UIColor darkGrayColor];
            headerLabel.font = [UIFont boldSystemFontOfSize:16];
            headerLabel.frame = CGRectMake(10, 7, 260.0, 44.0);
            headerLabel.textAlignment = UITextAlignmentCenter;
            NSDictionary *dictionary = [self.data objectAtIndex:section];
            headerLabel.text = [dictionary objectForKey:@"Title"];

            [customView addSubview:headerLabel];


            // add button to right corner of section
        UIButton* headerButton = [[UIButton alloc] initWithFrame:CGRectMake(10, 0, 320, 44)];
            headerButton.center = CGPointMake( 160.0, 22.0);
            headerButton.backgroundColor = [UIColor clearColor];
            headerButton.tag = section;
            [headerButton   addTarget:self action:@selector(expandSection:) forControlEvents:UIControlEventTouchUpInside];

            [customView addSubview:headerButton];

            return customView;
}

My Animation Method:

- (void) expandSection:(id)sender {

    if (expandedSection == [sender tag]) {
        expandedSection = -1;
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
    }else if (expandedSection == -1){
        expandedSection = [sender tag];
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
    }else{
        [self.tableView beginUpdates];  
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:expandedSection] withRowAnimation:UITableViewRowAnimationNone];
        expandedSection = [sender tag];
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView endUpdates]; 

    }
    //[self.tableView reloadData];
}

I am not exactly sure whats going on, but the instances suggest that I need to dealoc something. I've tried a few things but I can't figure this out. Anyone help on this would be great!

Edit: I believe the problem is that reloadSections is causing the custom view to instance. I can't release the view because I need it as a reference to do the update for the animation. Any ideas on what I can do to fix this?


回答1:


Solution found.

The table needed to be reloaded before every change. This way the table is at the latest state before making any changes.

add [self.tableView reloadData]; as the fist entry in the "expandSection" method.

CODE:

- (void) expandSection:(id)sender {

  [self.tableView reloadData];

    if (expandedSection == [sender tag]) {
        expandedSection = -1;
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
    }else if (expandedSection == -1){
        expandedSection = [sender tag];
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
    }else{
        [self.tableView beginUpdates];  
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:expandedSection] withRowAnimation:UITableViewRowAnimationNone];
        expandedSection = [sender tag];
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView endUpdates]; 

    }
    //[self.tableView reloadData];
}



回答2:


I had a similar issue which was caused by using dynamic height cells. I had an expandable custom header view and when I was updating tableView to insert and remove the associated rows of the section (meaning that they were expanding, respectively collapsing), the section header which was a subclass of UITableViewHeaderFooterView was not recycled. So basically a new one was allocated and added over the old one resulting in overlapping views. The cell identifier was properly set so must have been something else. When I removed tableView.sectionHeaderHeight = UITableViewAutomaticDimension and implemented func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat the view got properly recycled and only one header view was displayed for each section.

Another solution that I turned out to actually work was to use UITableViewCell instead of UITableViewHeaderFooterView and when you return in func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? you just return cell.contenView, this will work because the method requires to return a UIView and since the contentView of the UITableViewCell is a UIView it works just fine. The idea behind is to use the recycling mechanism of UITableView through UITableViewCell and just return its content after you configure it.

Conclusion. The problem it is very possible to be caused by UITableViewHeaderFooterView when is used with self sizing tableView cells and UITableViewAutomaticDimension instead of manually calculating cell height.



来源:https://stackoverflow.com/questions/2350032/uitableview-custom-section-header-duplicate-issue

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