滚动 UITableView 时单选按钮未选中
Posted
技术标签:
【中文标题】滚动 UITableView 时单选按钮未选中【英文标题】:Radio buttons get unselected while scrolling UITableView 【发布时间】:2015-08-05 07:30:19 【问题描述】:我在 UITableView Cell 上有两个单选按钮。我可以在向下滚动 UITableView 时选择其中一个,但是当我向上滚动 tableview 时,所有单选按钮都会被取消选中。滚动后,我也想让它们保持选中状态,但我无法做到这一点......所以请任何有解决方案的人帮助我。谢谢
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"cell";
customCell *cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
leftBtnclick.tag=999;
[leftBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
[leftBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
if (screenHeight == 667)
[leftBtnclick setFrame:CGRectMake(50, 59, 30, 30)];
else if(screenHeight == 480)
[leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];
[leftBtnclick addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.leftOptBtn addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:leftBtnclick];
rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
rightBtnclick.tag=1000;
[rightBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
[rightBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
if (screenHeight == 667)
[rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
else if(screenHeight == 480)
[leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];
[rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
[rightBtnclick addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.rightOptBtn addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:rightBtnclick];
cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
cell.questionLbl.text = [questionArray objectAtIndex:indexPath.row];
[cell.leftOptBtn setTitle:[leftOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
[cell.rightOptBtn setTitle:[rightOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
return cell;
-(void)leftTickBtnClicked:(id)sender
UIButton *leftTickBtn=(UIButton *)sender;
leftTickBtn.selected=!leftTickBtn.selected;
for(UIView *vw in [[sender superview]subviews])
if([vw isKindOfClass:[UIButton class]] && vw.tag==1000)
UIButton *rightTickBtn=(UIButton *)vw;
if(leftTickBtn.selected)
rightTickBtn.selected=NO;
else
rightTickBtn.selected=YES;
-(void)rightTickBtnClicked:(id)sender
UIButton *rightTickBtn=(UIButton *)sender;
rightTickBtn.selected=!rightTickBtn.selected;
for(UIView *vw in [[sender superview]subviews])
if([vw isKindOfClass:[UIButton class]] && vw.tag==999)
UIButton *leftTickBtn=(UIButton *)vw;
if(rightTickBtn.selected)
leftTickBtn.selected=NO;
else
leftTickBtn.selected=YES;
【问题讨论】:
这个问题有时会因重用 tableviewcell 而出现。删除if
语句并将NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil]; cell = [nib objectAtIndex:0];
从if
中写入这些行,然后重试。
还是不行......@SweetAngel
您的 tableview 中有多少行?
16 行 ...@SweetAngel
【参考方案1】:
您只创建了一个leftTickBtn
和rightTickBtn
,并在每次创建行时对其进行更新。所以最后不管你用单选按钮做了什么,它只影响到最后一个按钮。
更新您的代码如下:
UIButton *leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
leftBtnclick.tag=999+indexPath.row;
UIButton *rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
rightBtnclick.tag=1000+indexPath.row;
并实现如下方法:
- (IBAction)leftTickBtnClicked:(UIButton *)sender
sender.selected = TRUE;
UITableViewCell *cell = [tblAppointment cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1000-sender.tag inSection:0]];
for (id view in cell.contentView.subviews)
if ([view isKindOfClass:[UIButton class]])
// your code
UIButton *btnRight = (UIButton *)view;
if (sender.selected == TRUE)
btnRight.selected = FALSE;
else
btnRight.selected = TRUE;
和
- (IBAction)rightTickBtnClicked:(UIButton *)sender
sender.selected = TRUE;
UITableViewCell *cell = [tblAppointment cellForRowAtIndexPath:[NSIndexPath indexPathForRow:999-sender.tag inSection:0]];
for (id view in cell.contentView.subviews)
if ([view isKindOfClass:[UIButton class]])
// your code
UIButton *btnLeft = (UIButton *)view;
if (sender.selected == TRUE)
btnLeft.selected = FALSE;
else
btnLeft.selected = TRUE;
【讨论】:
感谢您的宝贵时间,但它对我不起作用...遇到同样的问题【参考方案2】:由于可重复使用单元的工作方式,您遇到了这个问题。
当您滚动离开您在单选按钮上进行更改的单元格,然后尝试滚动回该特定行时,可重复使用的单元格dequeueReusableCellWithIdentifier
并不能保证它将出列您所做更改的完全相同的单元格,并且很可能它将使您未进行任何更改的单元格出列
您需要跟踪cellForRowAtIndexPath
之外的列表中的按钮选择,并将选择重新分配给cellForRowAtIndexPath
中的单选按钮,这与每次使用cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
分配单元格文本的想法相同,方法是使用数组中的 indexPath.row
请参阅下面代码的修改 [1] 、 [2] 和 [3] (尚未测试但您明白了)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"cell";
customCell *cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
leftBtnclick.tag=999;
[leftBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
[leftBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
if (screenHeight == 667)
[leftBtnclick setFrame:CGRectMake(50, 59, 30, 30)];
else if(screenHeight == 480)
[leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];
[leftBtnclick addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.leftOptBtn addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:leftBtnclick];
rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
rightBtnclick.tag=1000;
[rightBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
[rightBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
if (screenHeight == 667)
[rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
else if(screenHeight == 480)
[leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];
[rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
[rightBtnclick addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.rightOptBtn addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:rightBtnclick];
cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
cell.questionLbl.text = [questionArray objectAtIndex:indexPath.row];
[cell.leftOptBtn setTitle:[leftOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
[cell.rightOptBtn setTitle:[rightOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
//[1]Set values for left and right
rightTickBtn.selected = [RightTicksArray objectAtIndex:indexPath.row];
leftTickBtn.selected = [LeftTicksArray objectAtIndex:indexPath.row];
return cell;
-(void)leftTickBtnClicked:(id)sender
UIButton *leftTickBtn=(UIButton *)sender;
leftTickBtn.selected=!leftTickBtn.selected;
for(UIView *vw in [[sender superview]subviews])
if([vw isKindOfClass:[UIButton class]] && vw.tag==1000)
UIButton *rightTickBtn=(UIButton *)vw;
if(leftTickBtn.selected)
rightTickBtn.selected=NO;
else
rightTickBtn.selected=YES;
//[2]Update RightTickArray At Pos
[RightTickArray objectAtIndex:indexPath.row] = leftTickBtn.selected;
-(void)rightTickBtnClicked:(id)sender
UIButton *rightTickBtn=(UIButton *)sender;
rightTickBtn.selected=!rightTickBtn.selected;
for(UIView *vw in [[sender superview]subviews])
if([vw isKindOfClass:[UIButton class]] && vw.tag==999)
UIButton *leftTickBtn=(UIButton *)vw;
if(rightTickBtn.selected)
leftTickBtn.selected=NO;
else
leftTickBtn.selected=YES;
//[3]Update LeftTickArray At Pos
[LeftTicksArray objectAtIndex:indexPath.row] = leftTickBtn.selected;
【讨论】:
您的想法是正确的,但您的代码对我不起作用。修改 2) 和 3) 给出错误 @alex 对不起,我当时没有 Mac 来正确测试它,如果它对你有帮助,请点赞【参考方案3】:我的问题得到了解决方案。 UITableView 单元格在滚动时可重用,这就是单选按钮选择消失的原因。因此,解决方案是将您的选择存储在一个数组中,并在 cellForRowAtIndexPath 中使用该数组。见代码。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"cell";
customCell *cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
leftBtnclick.tag=999;
cell.leftOptBtn.tag=999;
[leftBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
[leftBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
[leftBtnclick setFrame:CGRectMake(50, 59, 30, 30)];
[leftBtnclick addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.leftOptBtn addTarget:self action:@selector(leftBtnClicked) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:leftBtnclick];
rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
rightBtnclick.tag=1000;
cell.rightTickBtn.tag=1000;
[rightBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
[rightBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
[rightBtnclick setFrame:CGRectMake(190, 59, 30, 30)];
[rightBtnclick addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.rightOptBtn addTarget:self action:@selector(rightBtnClicked) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:rightBtnclick];
cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
cell.questionLbl.text = [questionArray objectAtIndex:indexPath.row];
[cell.leftOptBtn setTitle:[leftOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
[cell.rightOptBtn setTitle:[rightOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
if ([[answerArray objectAtIndex:indexPath.row] isEqualToString:@"YES"])
leftBtnclick.selected=YES;
rightBtnclick.selected=NO;
else if ([[answerArray objectAtIndex:indexPath.row] isEqualToString:@"NO"])
leftBtnclick.selected=NO;
rightBtnclick.selected=YES;
else
leftBtnclick.selected=NO;
rightBtnclick.selected=NO;
return cell;
-(void)leftTickBtnClicked:(id)sender
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:questionTable];
NSIndexPath *indexPath1 = [questionTable indexPathForRowAtPoint:buttonPosition];
[answerArray replaceObjectAtIndex:indexPath1.row withObject:@"YES"];
UIButton *leftTickBtn=(UIButton *)sender;
leftTickBtn.selected=!leftTickBtn.selected;
for(UIView *vw in [[sender superview]subviews])
if([vw isKindOfClass:[UIButton class]] && vw.tag==1000)
UIButton *rightTickBtn=(UIButton *)vw;
if(leftTickBtn.selected)
rightTickBtn.selected=NO;
else
rightTickBtn.selected=YES;
NSLog(@"Answer Array: %@",answerArray);
-(void)rightTickBtnClicked:(id)sender
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:questionTable];
NSIndexPath *indexPath1 = [questionTable indexPathForRowAtPoint:buttonPosition];
[answerArray replaceObjectAtIndex:indexPath1.row withObject:@"NO"];
UIButton *rightTickBtn=(UIButton *)sender;
rightTickBtn.selected=!rightTickBtn.selected;
for(UIView *vw in [[sender superview]subviews])
if([vw isKindOfClass:[UIButton class]] && vw.tag==999)
UIButton *leftTickBtn=(UIButton *)vw;
if(rightTickBtn.selected)
leftTickBtn.selected=NO;
else
leftTickBtn.selected=YES;
NSLog(@"Answer Array: %@",answerArray);
【讨论】:
以上是关于滚动 UITableView 时单选按钮未选中的主要内容,如果未能解决你的问题,请参考以下文章