正确子类化和重用 UITableViewHeaderFooterView
Posted
技术标签:
【中文标题】正确子类化和重用 UITableViewHeaderFooterView【英文标题】:Correct subclassing and reusing of UITableViewHeaderFooterView 【发布时间】:2013-08-25 17:08:35 【问题描述】:我有一个 UITableView,其中有部分标题,可以点击以展开或折叠该部分。在我的特定示例中,每个部分只有一行,可见(部分展开)或隐藏(部分折叠)。 作为部分标题,我使用自定义 UITableViewHeaderFooterView - HeaderAccountView。我在 Interface Builder 创建了 *.xib 文件,并将其自定义类设置为我的 HeaderAccountView(仍在 IB 字段中)。
在我的 HeaderAccountView.h 和 HeaderAccountView.m 文件中,init
方法或类似的东西没有任何更改 - 只有一些功能可以突出显示自己(选定部分)等。
在我的主 ViewController .m 文件中
- (void)viewDidLoad
[super viewDidLoad];
.........
.........
UITableView *tableView = (id)[self.view viewWithTag:1];
UINib *nib= [UINib nibWithNibName:@"HeaderAccountView" bundle:nil];
[tableView registerNib:nib forHeaderFooterViewReuseIdentifier:@"HeaderCell"];
然后
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
HeaderAccountView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"HeaderCell"];
if (headerView==nil)
headerView = [[HeaderAccountView alloc]
initWithReuseIdentifier:@"HeaderCell"];
return headerView;
当我运行项目时,一切正常 - 部分加载了所需的数据,当部分收到点击时 - 它突出显示(如标准单元格)。
但是当我将 tableview 滚动到底部时,例如从选定的突出显示部分,并且这个突出显示的部分在视图中已经不可见 - 刚刚从底部出现的那个部分 - 已经突出显示!
我知道这是因为它创建了我的 HeaderAccountView 的新实例,并将属性 BOOL selected
设置为 YES。
但我是 Objective-c(和编码)的新手,不明白如何正确解决这个问题。
我尝试像这样使用我的自定义 UITableViewHeaderFooterView 的prepareForReuse
方法
HeaderAccountView.m:
-(void) prepareForReuse
self.selectedBackground.alpha = 0;
效果更好 - 但现在我遇到了另一个问题 - 当我返回第一个(真正)选择并突出显示的部分时 - 它显然没有突出显示。
感谢您的帮助,如果是基本问题,我们深表歉意。
【问题讨论】:
【参考方案1】:您必须手动保留所选标题索引的列表。
接下来,在您的视图控制器中实现方法 tableView:willDisplayHeaderView: 以在标题显示时刷新它。
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
view.selectedBackground.alpha = ([_highlightedHeadersList containsObject:@(section)] ? 0.0f : 1.0f);
您必须在 _highlightedHeadersList 中添加/删除索引。
【讨论】:
谢谢,这正是我想要的答案。【参考方案2】:我使用以下方法完成了此操作。在表视图控制器中,我创建了一个属性 (NSInteger),并将其命名为 sectionForSelectedHeader。最初将其设置为 -1,因此最初不会选择任何部分。
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
RDHeader *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Header"];
header.tag = section;
if (header.gestureRecognizers.count == 0)
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(headerSelected:)];
[header addGestureRecognizer:tapper];
header.selected = (self.sectionForSelectedHeader == section)? 1 : 0;
return header;
-(void)headerSelected:(UITapGestureRecognizer *) tapper
if ([(RDHeader *)tapper.view selected] != 1)
self.sectionForSelectedHeader = tapper.view.tag;
else
self.sectionForSelectedHeader = -1;
[self.tableView reloadData];
然后在我的自定义标头子类中,我有一个方法 setSelected:(selected 是 RDHeader 类中的一个 NSInteger 属性),如下所示:
-(void)setSelected:(NSInteger)selected
_selected = selected;
if (selected)
self.contentView.backgroundColor = [UIColor orangeColor];
else
self.contentView.backgroundColor = [UIColor yellowColor];
【讨论】:
谢谢,但可能是因为我使用动画仅突出显示 tableViewwillDisplayHeaderView
不起作用。以上是关于正确子类化和重用 UITableViewHeaderFooterView的主要内容,如果未能解决你的问题,请参考以下文章