【问题标题】:Maintain state of custom button in UITableview cell when scrolls滚动时保持 UITableview 单元格中自定义按钮的状态
【发布时间】:2015-06-13 00:07:15
【问题描述】:

我知道这个问题与其他问题非常相似,但我没有使用这种方法解决问题。我遵循大多数可用的解决方案,但它对我不起作用.. 我知道当 tableview 滚动它重用单元格时,但我不知道维护按钮状态的方法。我会尝试以下链接

我做了所有的事情。使用标签,使用接触点,但似乎没有什么对我有用。所以请帮帮我..这是我的示例代码

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];


/*
 *  Set button for cell to subscribe with it
 */
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;


[cell.btnsubscribe addTarget:self action:@selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];

if (![_arraybtnState containsObject:listid] )
    {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
        [cell.btnsubscribe setSelected:YES];
    }
    else {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
        [cell.btnsubscribe setSelected:NO];
    }

  return cell;
  }

_arrbtnstate 包含用户关注的 id。
并且 listid 包含唯一 id 也来自数据库

还有点击事件方法...

- (IBAction)clickBtnSubscribe:(id)sender {

UIButton *button = (UIButton*)sender;
NSLog(@"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];

if (button.selected) {
    [self.arraybtnState addObject:tagnum];
    [button setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    NSLog(@"Subscribe");
    [self subscribeButton:button.tag];
    [button setSelected:NO];
}
else
{
    [self.arraybtnState removeObject:tagnum];
    [button setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    NSLog(@"unsubscribe");
    [self unsubscribeButton:button.tag];
    [button setSelected:YES];
}

}   

注意:在此代码中,按钮是在情节提要中创建的。但我也会尝试不使用情节提要。

【问题讨论】:

  • 这不起作用,因为您总是对所有单元格使用相同的按钮。您必须为单元格创建一个新按钮。
  • 请参阅我对 swift 2.1 的回答。效果很好。 stackoverflow.com/questions/25257378/…

标签: ios objective-c iphone uitableview


【解决方案1】:

首先要更改cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303]; 这一行。请按照以下步骤尝试

  1. 在自定义subcategoryCell 中将IBOutlet 连接到btnsubscribe
  2. 在情节提要中,您可以将选定图像和非正常图像设置为UIButton,这里是btnsubscribe。如果您觉得困难,请关注this
  3. cellForRowAtIndexPath: 中删除以下行

    [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
    
  4. 更新以下行

    if (![_arraybtnState containsObject:listid] )
    {
         [cell.btnsubscribe setSelected:YES];
    }
    else {
         [cell.btnsubscribe setSelected:NO];
    }
    

或者干脆[cell.btnsubscribe setSelected:(![_arraybtnState containsObject:listid] )];

  1. addTarget 保留在单元格中作为行方法(因为您有自定义单元格类,最好将按钮操作移动到单元格类并通过回调或委托将结果传递给视图控制器。现在不讨论,但建议)并通过删除更新clickBtnSubscribe:

    [button setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    [button setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    

这些行。假设其他部分工作正常。

【讨论】:

  • 好的,我会试试这个...但现在我使用的是 swift 而不是自定义类...所以为此我必须使用 xib 制作新的自定义类?对
  • 如果您使用情节提要,您可以在情节提要本身中添加自定义原型单元格。这个想法是为 uibutton 的 2 个状态设置两个不同的图像并仅更改其状态。图片会自动变化
  • 并且使用自定义单元格,您可以连接 IBOutlet 而无需使用带有标签选项的视图获取按钮。也可以用 indexpath 更新标签来识别行
  • ohhh...man ...从这么多天开始...
  • 欢迎 @Bhavin .. 很高兴知道它对您有用.. 如果您有足够的时间,请尝试将单元格中 uibutton 的操作移动到自定义单元格类并通过回调将所需的响应发送到 viewcontroller :) .快乐编码..
【解决方案2】:

在这两种情况下,即 UIControlStateNormal,您正在为按钮的正常状态设置选定和未选定的图像。 当您使用 selected 方法时,您不需要再次 setImage。只需在 cellForRowAtIndexpath 或 xib 中正确设置正常的图像和按钮的选定状态。你已经完成了。

先去掉clickBtnSubscribe:()方法中的设置图片。

现在在您的故事板中设置正常和选定状态的图像。 也像您在视图中所做的那样,在 indexpath 的行中删除单元格中的 set Image。

【讨论】:

    【解决方案3】:

    您可以将按钮的状态保持为-

    // 只初始化一次数组

    _arraybtnState = [[NSMutableArray alloc] init];
    

    // 索引路径处的行单元格将是

    //最初每个单元格都会有跟随图像

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
      cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
    
    [cell.btnsubscribe setTag: indexPath.row];
    [cell.btnsubscribe addTarget:self action:@selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
    
        if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] )
        {
            [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
            [cell.btnsubscribe setSelected:YES];
        }
        else 
        {
            [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
            [cell.btnsubscribe setSelected:NO];
        }
    
      return cell;
      }
    
    - (IBAction)clickBtnSubscribe:(id)sender {
    
    UIButton *button = (UIButton*)sender;
    NSLog(@"selected button tag %li", (long)button.tag);
    NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
    
    if (button.selected) {
        [self.arraybtnState addObject:tagnum];
        NSLog(@"Subscribe");
        [self subscribeButton:button.tag];
        [button setSelected:NO];
    }
    else
    {
        [self.arraybtnState removeObject:tagnum];
        NSLog(@"unsubscribe");
        [self unsubscribeButton:button.tag];
        [button setSelected:YES];
    }
    
        //after doing modification update the respective row as
    
        UIButton *button = (UIButton *)sender;
    
        // Find Point in Superview
        CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
    
        // Infer Index Path
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInSuperview];
    
        //relaod the row
        NSArray* indexPathModel = [NSArray arrayWithObjects:indexPath, nil];
        [self.tableView reloadRowsAtIndexPaths: indexPathModel withRowAnimation:UITableViewRowAnimationNone];
    
    }
    

    重新加载行会将模式中所做的更改反映到 UI。

    【讨论】:

    • 我通过情节提要将按钮放在表格中...所以有什么不同吗??
    • 不,它不会有任何区别,只要您正确更新模型,然后更新相应的行
    【解决方案4】:

    我认为您可以将此行放入 viewDidLoad 或在加载所有已订阅的内容之后。

       _arraybtnState = [NSMutableArray arrayWithArray:[self.strSubscribe componentsSeparatedByString:@","]];
    

    那么 cellForRowAtIndexPath 将如下所示

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
      cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
    
    
    /*
     *  Set button for cell to subscribe with it
     */
    cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
    cell.btnsubscribe.tag = indexPath.row ;
    
    [cell.btnsubscribe addTarget:self action:@selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
    
         if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] ) {
    
            [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
        }
        else {
            [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
        }
    
      return cell;
      }
    

    然后btn点击方法为

    - (IBAction)clickBtnSubscribe:(id)sender {
    
    UIButton *button = (UIButton*)sender;
    NSLog(@"selected button tag %li", (long)button.tag);
    NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
    
    
      if (![_arraybtnState containsObject:tagnum] )
      {
          [_arraybtnState addObject:tagnum];
          [button setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
        NSLog(@"Subscribe");
        [self subscribeButton:button.tag];
    
    
        }
        else {
    
        [self.arraybtnState removeObject:tagnum];
        [button setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
        NSLog(@"unsubscribe");
        [self unsubscribeButton:button.tag];
    
    
        }
    
    }  
    

    【讨论】:

      【解决方案5】:

      两种简单的解决方案,实施起来非常快:

      1. 跟踪数组/字典中的状态

      你可以将你的状态存储在一个状态数组中,我举个例子。

      (注意:我是在没有编译的情况下编写代码,我可能会拼错一些东西,请随时编辑我的帖子)

      在你的viewDidLoad

        arrState = [[NSMutableArray alloc]init];
        for (yourObject *object in dataArray){  
            //For every object that you use to load your tableview, this can be strings or anything really
             [arrState addObject:@NO];
      
          }
      

      在你的cellForRow

      ...
      //This will either put YES or NO depending on the element in the state array.
      [cell.button setSelected:[arrState objectAtIndex:indexPath.row]];
      ...
      

      砰,完成。

      1. 您还可以在数据库或任何持久性内容中对此进行跟踪,然后您只需为所选记录加载字段中包含的任何内容。例如,如果我们谈论的是收藏夹之类的东西,或者在用户做出其他决定之前会一直存在的东西,这将更加相关。如果只是为了在视图的生命周期内跟踪按钮状态,请忽略这部分答案。

      如果您需要让它永远活着(即使应用程序关闭),那么您很可能需要一个数据库:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-27
        相关资源
        最近更新 更多