2

我更喜欢使用 UITableView 创建具有 2 级层次结构的表,如这张图片。每次用户点击标题时,内容都会折叠或展开。经过3天的研究,我发现有2个技术:

1.自定义 UITableViewCell 本身带有另一个表

2.使用节标题视图。

现在我决定使用第二个。而且因为UITableView 不重用剖面视图(虽然 UITableView 包含 2 个私有变量:_reusableHeaderViews & _reusableFooterViews:),我创建了一些自定义方法来完成这项任务。一切都很好,除了 1 个错误:当我使用方法reloadSections:withRowAnimationUITableViewRowAnimationFade时,标题视图变为空白视图。

这是我的代码:

#import "MasterViewController.h"

@interface MasterViewController () 
//remember current section
@property (assign, nonatomic) NSInteger curSession;
@property (strong, nonatomic) NSMutableDictionary *reusableHeaderViews;
@end

@implementation MasterViewController

@synthesize reusableHeaderViews = _reusableHeaderViews;
@synthesize tableView = _tableView;
@synthesize curSession = _curSession;
@synthesize detailViewController = _detailViewController;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.title = NSLocalizedString(@"Master", @"Master");
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.curSession = -1;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

//method for adding header view into reuse-array
-  (void)registerHeaderView:(UITableViewCell *)headerView forReuseIdentifier:(NSString *)reuseIdentifier
{
    NSMutableDictionary *reusableDictionary  = [self reusableHeaderViews];
    if (reusableDictionary == nil)
    {
        reusableDictionary = [[NSMutableDictionary alloc] init];  //creates a storage dictionary if one doesn’t exist
        self.reusableHeaderViews = reusableDictionary;
    }

    NSMutableArray *arrayForIdentifier = [[self reusableHeaderViews] objectForKey:reuseIdentifier];
    if (arrayForIdentifier == nil)
    {
        //creates an array to store views sharing a reuse identifier if one does not exist
        arrayForIdentifier = [[NSMutableArray alloc] init];        
        [reusableDictionary setObject:arrayForIdentifier forKey:reuseIdentifier];
    }

    [arrayForIdentifier addObject:headerView];
}

//get header view in reuse-array
- (UITableViewCell *)reuseableHeaderForIdentifier:(NSString *)reuseIdentifier
{
    NSMutableArray *arrayOfViewsForIdentifier = [[self reusableHeaderViews]  objectForKey:reuseIdentifier];

    if (arrayOfViewsForIdentifier == nil)
    {
        return nil;  //We don’t have any of this kind!
    }

    NSInteger indexOfAvailableHeaderView = [arrayOfViewsForIdentifier indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)
                                            {
                                                //If my view doesn’t have a superview, it’s not on-screen.
                                                return ![obj superview];
                                            }];

    if (indexOfAvailableHeaderView != NSNotFound)
    {
        UITableViewCell *headerView = [arrayOfViewsForIdentifier objectAtIndex:indexOfAvailableHeaderView];
        return headerView;    //Success!
    }

    return nil;
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 15;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (_curSession == section)
        return section;
    return 0;
}

- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *headerReuseIdentifier = @"Header";
    UITableViewCell *cell = [self reuseableHeaderForIdentifier:headerReuseIdentifier];
    if(cell == nil) 
    {
        //Didn’t locate a reusable
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@""];
        [self registerHeaderView:cell forReuseIdentifier:headerReuseIdentifier];
        UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openSection:)];
        tapGR.numberOfTapsRequired = 1;
        [cell addGestureRecognizer:tapGR];
        cell.backgroundColor = [UIColor redColor];
    }
    cell.tag = section;
    cell.textLabel.text = [NSString stringWithFormat:@"Section title %i", section];

    return cell;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    cell.textLabel.text = [NSString stringWithFormat:@"Row %i - section %i", indexPath.row, indexPath.section];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

}

- (void) openSection:(id)sender

{
    NSInteger section = [[(UITapGestureRecognizer*)sender view] tag];
    if(_curSession == -1)
    {
        _curSession = section;
        [_tableView reloadSections:[NSIndexSet indexSetWithIndex:_curSession] withRowAnimation:UITableViewRowAnimationFade];
    }
    else if(_curSession == section)
    {
        _curSession = -1;
        [_tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
    }
    else if(_curSession != section)
    {
        NSInteger temp = _curSession;
        _curSession = -1;
        [_tableView reloadSections:[NSIndexSet indexSetWithIndex:temp] withRowAnimation:UITableViewRowAnimationFade];
        _curSession = section;
        [_tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
    }
}

@end
4

1 回答 1

0

这有点晚了,但也许有人会有类似的问题。

你可以尝试使用这个组件:https ://github.com/serverdensity/ios-SDNestedTable

于 2013-04-07T12:16:11.540 回答