更新4.0
似乎iOS 4.0在这里改变了一些东西。根据我的第一次快速检查,相同的代码在所描述的场景中为节标题生成了错误的背景!
原始
我有一个UITableView分组样式,带有自定义页眉和页脚视图。在页脚里面我放了一个UILabel和一个UIButton。
单击按钮隐藏或显示一些行,更新页脚视图中的UILabel,最后调整页脚视图的大小。
基本上一切都运转正常。但是文本离开标签没有在屏幕上更新。它在UILabel文本属性中更新,但只有当我将部分页脚滚动到可见区域之外并向后滚动它时,它才会更新。所以这是UITableView的典型重绘问题。
我尝试了各种方法强制更新,例如needsLayout等。没有任何帮助。
我已经看到了一些相关的问题,但有一些不同的行为,没有解决方案。任何帮助/想法?
谢谢,Gerd
更新:
部分页脚出现问题,所以这是我的viewForFooterInSection。
基本上我想折叠/展开一个部分,但不是完全(这是一件容易的事)而只是空单元格(ItemSize为空)。如果它是折叠的,则footerView很大,如果它被展开则会缩小。此外,标签文字也会改变。
- (UIView *)tableView: (UITableView *)tableView viewForFooterInSection: (NSInteger)section{
NSLog(@"viewForFooterInSection section:%i", section);
UIButton *myView;
UILabel *label;
if ([[[self.sectionStatus objectAtIndex:section] valueForKey:@"collapseStatus"] isEqual:@"collapse"]){
myView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 52)];
[myView setBackgroundImage:[UIImage imageNamed:@"ItemViewFooter.png"] forState:UIControlStateNormal];
label = [[UILabel alloc] initWithFrame:CGRectMake(20, 32, 300, 20)];
label.text = NSLocalizedString(@"list_expand",@"");
} else { //is expanded
myView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
[myView setBackgroundImage:[UIImage imageNamed:@"ListCollapseExpand.png"] forState:UIControlStateNormal];
label = [[UILabel alloc] initWithFrame:CGRectMake(20, 1, 300, 20)];
label.text = NSLocalizedString(@"list_collapse",@"");
}
myView.tag=section;
[myView addTarget:self action:@selector(collapseExpandAction:) forControlEvents:UIControlEventTouchUpInside];
myView.backgroundColor = [UIColor clearColor];
myView.adjustsImageWhenHighlighted = NO;
myView.showsTouchWhenHighlighted = YES;
label.textColor = FONTCOLOR;
label.font = [UIFont systemFontOfSize:14];
label.numberOfLines = 1;
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
[myView addSubview:label];
return myView;
};
在按钮操作方法中,我存储了部分折叠/展开的状态和显示的行数。比我删除或插入行。 (必须使用插入/删除,因为我需要动画)。
- (void) collapseExpandSection: (NSInteger) section{
NSMutableArray *paths = [NSMutableArray arrayWithCapacity:10];
NSInteger row;
NSInteger numberOfDisplayedItems=[[[self.sectionStatus objectAtIndex:section] valueForKey:@"numberOfDisplayedRows"] intValue];
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
NSInteger numberOfAllItems=[sectionInfo numberOfObjects];
Item *tmpItem=nil;
NSSet *itemsWithSizes=nil;
//filter not used cells
for ( row = 0; row < numberOfAllItems; row++ ) {
tmpItem=[fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:row inSection:section]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"itemSize != nil"];
NSSet *itemsWithSizes = [tmpItem.itemSizes filteredSetUsingPredicate:predicate];
if ([itemsWithSizes count]==0){
[paths addObject:[NSIndexPath indexPathForRow:row inSection:section]]; //all unused cells
};
}
if (numberOfDisplayedItems == numberOfAllItems){ //currently all shown => Collapse
[self.tableView beginUpdates];
[[self.sectionStatus objectAtIndex:section] setValue:[NSNumber numberWithInt:(numberOfDisplayedItems-[paths count])] forKey:@"numberOfDisplayedRows"];
[[self.sectionStatus objectAtIndex:section] setValue:@"collapse" forKey:@"collapseStatus"];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
} else { //Not all shown so expand with the unused cells
[[self.sectionStatus objectAtIndex:section] setValue:[NSNumber numberWithInt:(numberOfDisplayedItems+[paths count])] forKey:@"numberOfDisplayedRows"];
[[self.sectionStatus objectAtIndex:section] setValue:@"expand" forKey:@"collapseStatus"];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
}
return;
};
一切都做得很好。块开始/结束更新后,将为每个部分调用viewForFooter,并在属性中设置正确的标签文本。但是显示无法正确更新。一旦强制重新显示(滚动滚动),显示就可以了。
答案 0 :(得分:4)
有2个问题
第一个问题是部分页脚没有更新。
更新后请尝试拨打[tableView reloadData]
或[tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade]
(可能是dalay)
第二个问题是myView
和label
中的内存泄漏。
另外,为什么在使用按钮的内部标签时会使用标签?
附:不要直接分配UIButton
对象,因为它是工厂的。请改为呼叫[UIButton buttonWithType:UIButtonTypeCustom]
。
更新:更新的另一种方法是通过访问页脚视图直接更新页脚。
- (void) collapseExpandSection: (NSInteger) section{
检查该部分是否真的是您的按钮
- (void) collapseExpandSection: (UIButton*) sender{
// Do update of sender here
// Do other stuff
}
您还可以尝试下一个技巧:在委托中创建UIView对象,在其上添加按钮和标签,然后返回对象视图本身的实例。
答案 1 :(得分:3)
我的问题是我正在扩展Section标题以显示搜索栏,但在我滚动UITableView之前它不会重绘视图。
我有自己的SectionHeader类,它将UIView子类化并控制搜索内容。
在我的动画之后,我只是用它来强制更新。它不漂亮,但它有效。
CGPoint point = CGPointMake(((UIScrollView *)self.superview).contentOffset.x,
((UIScrollView *)self.superview).contentOffset.y+1);
[((UIScrollView *)self.superview) setContentOffset:point animated:NO];
point = CGPointMake(((UIScrollView *)self.superview).contentOffset.x,
((UIScrollView *)self.superview).contentOffset.y-1);
[((UIScrollView *)self.superview) setContentOffset:point animated:NO];
基本上强制UITableView向下滚动1个像素,向上滚动1个像素。
答案 2 :(得分:0)
I had an issue just like this where I wanted to update the section header after inserting a new row. I found that calling tableView reloadSections()
method with an animation setting of .None
after I call the insertRows method worked for me (both calls in the same tableView update block). I got the insert animation I wanted and also the section header was updated.