xcode UITableView 滚动和重绘问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8009990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UITableView scrolling and redraw issue
提问by applefreak
I know that if I have some images and subviews added in customized cell then I have to reuse the cell so that custom control won't appear on other cells but here I have other issue. I just want to have ImageView on first cell of first section so I have used IndexPath.Section==0 and IndexPath.Row==0 condition in following code but the problem is when I scroll table, the other cell will meet this condition and my code will create imageview on that cell as well. I have tried Tagging it and using same tagged cellView but it didn't help either. The cell issue is with disabling user interactions for few cells. Eventually after scrolling it disables user interactions for all cells. Is there anyway to resolve this?
我知道如果我在自定义单元格中添加了一些图像和子视图,那么我必须重用该单元格,以便自定义控件不会出现在其他单元格上,但在这里我还有其他问题。我只想在第一部分的第一个单元格上使用 ImageView 所以我在下面的代码中使用了 IndexPath.Section==0 和 IndexPath.Row==0 条件但问题是当我滚动表格时,另一个单元格将满足这个条件并且我的代码也会在该单元格上创建图像视图。我试过标记它并使用相同的标记 cellView 但它也没有帮助。单元问题是禁用少数单元的用户交互。最终滚动后,它会禁用所有单元格的用户交互。有没有办法解决这个问题?
Thanks.
谢谢。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.section == 0 && indexPath.row == 0) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"me.jpg"]] autorelease];
UIView *cellView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0,320,132)] autorelease];
[imageView setFrame: CGRectMake(10, 10, 54, 54)];
[cellView addSubview:imageView];
cell.backgroundView = cellView;
return cell;
} else if(indexPath.row == 0) {
NSString * title = [NSString string];
switch (indexPath.section) {
case 1:
title = @"Friends";
break;
case 2:
title = @"Accounts";
break;
case 3:
title = @"Stats";
break;
default:
title = nil;
break;
}
cell.textLabel.text = title;
cell.userInteractionEnabled = NO;
return cell;
}
cell.textLabel.text = @"Test";
return cell;
}
[RESOLVED] Correct code:
[已解决] 正确代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
if(indexPath.section == 0 && indexPath.row == 0) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"me.jpg"]] autorelease];
cell.imageView.image = imageView.image;
cell.textLabel.text = nil;
cell.textLabel.textColor = [UIColor clearColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.userInteractionEnabled = YES;
return cell;
} else if(indexPath.row == 0) {
NSString * title = [NSString string];
switch (indexPath.section) {
case 1:
title = @"Friends";
break;
case 2:
title = @"Accounts";
break;
case 3:
title = @"Stats";
break;
default:
title = nil;
break;
}
cell.imageView.image = nil;
cell.textLabel.text = title;
cell.textLabel.textColor = [UIColor redColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.userInteractionEnabled = NO;
return cell;
}
cell.imageView.image = nil;
cell.textLabel.text = [cellItems objectAtIndex:(rows+indexPath.row-1)];
cell.textLabel.textColor = [UIColor blueColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.userInteractionEnabled = YES;
return cell;
}
[IMPROVED CODE]
[改进的代码]
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *NormalCellIdentifier = @"NormalCell";
static NSString *TitleCellIdentifier = @"TitleCell";
NSString *neededCellType;
if(indexPath.section == 0 && indexPath.row == 0) {
neededCellType = TitleCellIdentifier;
} else {
neededCellType = NormalCellIdentifier;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:neededCellType];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:neededCellType] autorelease];
//Only add content to cell if it is new
if([neededCellType isEqualToString: TitleCellIdentifier]) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"me.jpg"]] autorelease];
cell.imageView.image = imageView.image;
}
}
if([neededCellType isEqualToString: NormalCellIdentifier]) {
NSString * title;
if(indexPath.row == 0) {
switch (indexPath.section) {
case 1:
title = @"Friends";
break;
case 2:
title = @"Accounts";
break;
case 3:
title = @"Stats";
break;
default:
title = nil;
break;
}
cell.textLabel.text = title;
cell.textLabel.textColor = [UIColor redColor];
cell.userInteractionEnabled = NO;
} else {
cell.userInteractionEnabled = YES;
cell.textLabel.textColor = [UIColor blueColor];
cell.textLabel.text = @"Test";
}
}
return cell;
}
采纳答案by Dancreek
The problem is that you are not allowing for the possibility that the cell that was correctly showing the image gets reused later and the image view is still in there.
问题是您不允许正确显示图像的单元格稍后被重用并且图像视图仍在那里。
Here are two solutions:
这里有两个解决方案:
set the tag value of the image view when you create it, then when you setup the cells, include code to check for and remove the old imageView if necessary.
assign different reuse identifiers to cells that need an image view and those that do not. Then make sure that you are only adding a new image view to cells when they are being created and not when they are being reused.
创建时设置图像视图的标签值,然后在设置单元格时,包含代码以检查并在必要时删除旧的图像视图。
为需要图像视图和不需要图像视图的单元格分配不同的重用标识符。然后确保您只在创建单元格时向单元格添加新的图像视图,而不是在重用它们时添加新的图像视图。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *NormalCellIdentifier = @"NormalCell"; static NSString *TitleCellIdentifier = @"TitleCell"; NSString *neededCellType;
if(indexPath.section == 0 && indexPath.row == 0) { neededCellType = TitleCellIdentifier; } else { neededCellType = NormalCellIdentifier; }
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:neededCellType];
if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:neededCellType] autorelease];
//Only add content to cell if it is new if([neededCellType isEqualToString: TitleCellIdentifier]) { UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"me.jpg"]] autorelease]; UIView *cellView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0,320,132)] autorelease]; [imageView setFrame: CGRectMake(10, 10, 54, 54)]; [cellView addSubview:imageView]; cell.backgroundView = cellView; } }
if([neededCellType isEqualToString: NormalCellIdentifier]) { NSString * title; if(indexPath.row == 0) {
switch (indexPath.section) { case 1: title = @"Friends"; break; case 2: title = @"Accounts"; break; case 3: title = @"Stats"; break; default: title = nil; break; } cell.textLabel.text = title; cell.userInteractionEnabled = NO;
}
else { cell.textLabel.text = @"Test"; return cell; } } }
(Those last few lines fell out of the code box). That should do it.
(最后几行不在代码框中)。那应该这样做。
回答by Stavash
I think your problem is that the reuse of cells makes it so that the cells that aren't being created as new cells have some properties set that you must redefine. For instance, try assigning cell.userInteractionEnabled = YES to all other cases and see what the result is.
我认为您的问题是单元格的重用使得未被创建为新单元格的单元格具有一些必须重新定义的属性集。例如,尝试将 cell.userInteractionEnabled = YES 分配给所有其他情况,看看结果是什么。