繁体   English   中英

自定义 UITableViewCell 中的按钮操作会影响其他单元格

[英]Button action in custom UITableViewCell affects other cells

我有一个TablewView ,它的原型UITableViewCell有自己的类,

自定义 UITableViewCell 类

import UIKit

class H_MissingPersonTableViewCell: UITableViewCell {

    @IBOutlet weak var strName: UILabel!
    @IBOutlet weak var imgPerson: UIImageView!
    @IBOutlet weak var Date1: UILabel!
    @IBOutlet weak var Date2: UILabel!
    @IBOutlet weak var MainView: UIView!
    @IBOutlet weak var btnGetUpdates: UIButton!
    @IBOutlet weak var btnComment: UIButton!
    @IBOutlet weak var btnReadMore: UIButton!
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

TableView 加载完美,数据源和委托工作正常。 但是,当我单击 IndexPath.row = 0(零)处的 BUTTON,然后向下滚动时,由于单击第 0 行中的 BUTTON,我会看到随机(?)或其他单元格也被突出显示...

这是我的 CellForRowAtIndexPath 代码:

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        println("called")
        var cell : CustomCell
        
        
        cell = tableView.dequeueReusableCellWithIdentifier("CustomCellID", forIndexPath: indexPath) as! CustomCell
        cell.strName.text = self.names[indexPath.row]
        cell.imgPerson.image = UIImage(named: "\(self.persons[indexPath.row])")!

        cell.btnGetUpdates.layer.borderColor = UIColor.darkGrayColor().CGColor
        cell.btnGetUpdates.layer.borderWidth = 1
        cell.btnGetUpdates.layer.cornerRadius = 5.0
        

        cell.btnComment.layer.borderColor = UIColor.darkGrayColor().CGColor
        cell.btnComment.layer.borderWidth = 1
        cell.btnComment.layer.cornerRadius = 5.0
        
        cell.btnReadMore.layer.borderColor = UIColor.darkGrayColor().CGColor
        cell.btnReadMore.layer.borderWidth = 1
        cell.btnReadMore.layer.cornerRadius = 5.0
        
        cell.dateMissingPersonPlace.text = self.MissingPeoplePlace[indexPath.row]
        cell.dateMissingPersonSince.text = self.MissingPeopleSince[indexPath.row]
        
        cell.btnGetUpdates.tag = indexPath.row
        cell.btnGetUpdates.addTarget(self, action: "GetUpdatesButton:", forControlEvents: .TouchUpInside)
        
        return cell
        
    }

在我的cell.btnGetUpdates 中,我在 CellForIndex 代码的最后一部分GetUpdatesButton 中放置了一个操作

这是代码:

func GetUpdatesButton(sender: UIButton){
    println("Button Clicked \(sender.tag)")

    var sen: UIButton = sender
    var g : NSIndexPath = NSIndexPath(forRow: sen.tag, inSection: 0)
    var t : CustomCell = self.myTableView.cellForRowAtIndexPath(g) as! CustomCell
    t.btnGetUpdates.backgroundColor = UIColor.redColor()
    }

问题是,不仅索引 0 中的按钮被突出显示,而且当我向下滚动 tableView 时,我还会看到来自其他索引/行的随机按钮被突出显示。

我哪里出错了,我怎么能只更新我点击的按钮......而不是其他按钮......

我有 20 个项目(20 行),当我单击第 0 行中的按钮时,第 3、6、9 行......也有突出显示的按钮。

第 0 行,单击按钮

第零行,单击按钮

第 3 行,按钮也被点击了,虽然我并没有真正点击它。 在此处输入图片说明

这是由于 UITableview 具有可重用单元策略而发生的。为了解决此问题,您需要在 cellForRowAtIndexPath 方法中维护一组选定项目,您必须验证该按钮是否被选定项目数组保持。 如果是,则应用选择样式,否则对其应用普通样式。

检查下面的 buttonclick 源代码:

func GetUpdatesButton(sender: UIButton) 
{
    var sen: UIButton = sender
    var g : NSIndexPath = NSIndexPath(forRow: sen.tag, inSection: 0)
    var t : CustomCell = self.myTableView.cellForRowAtIndexPath(g) as!   CustomCell
    t.btnGetUpdates.backgroundColor = UIColor.redColor()
   self.selectedButtonsArray.addObject(indexpath.row)
}

以下代码用于在 CellForRowAtIndexPath 中的按钮上应用样式:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell : CustomCell
    cell = tableView.dequeueReusableCellWithIdentifier("CustomCellID", forIndexPath: indexPath) as! CustomCell
    cell.strName.text = self.names[indexPath.row]
    cell.imgPerson.image = UIImage(named: "\(self.persons[indexPath.row])")!

    if(self.selectedButtonsArray.containsObject(indexpath.row)){

        cell.btnGetUpdates.backgroundColor = UIColor.redColor()
        cell.btnGetUpdates.layer.borderColor = UIColor.darkGrayColor().CGColor
        cell.btnGetUpdates.layer.borderWidth = 1
        cell.btnGetUpdates.layer.cornerRadius = 5.0

    }else{

        cell.btnGetUpdates.layer.borderColor = UIColor.darkGrayColor().CGColor
        cell.btnGetUpdates.layer.borderWidth = 1
        cell.btnGetUpdates.layer.cornerRadius = 5.0

   }

    cell.btnComment.layer.borderColor = UIColor.darkGrayColor().CGColor
    cell.btnComment.layer.borderWidth = 1
    cell.btnComment.layer.cornerRadius = 5.0

    cell.btnReadMore.layer.borderColor = UIColor.darkGrayColor().CGColor
    cell.btnReadMore.layer.borderWidth = 1
    cell.btnReadMore.layer.cornerRadius = 5.0

    cell.dateMissingPersonPlace.text = self.MissingPeoplePlace[indexPath.row]
    cell.dateMissingPersonSince.text = self.MissingPeopleSince[indexPath.row]

    cell.btnGetUpdates.tag = indexPath.row
    cell.btnGetUpdates.addTarget(self, action: "GetUpdatesButton:",forControlEvents: .TouchUpInside)

    return cell

}

我希望这有助于解决您的问题! 谢谢。

这是因为细胞正在被重用。 因此,当您使用按钮操作为单元格着色时,单元格的背景正在被绘制,我猜这工作正常,但情况是当您向上或向下滚动时,正在重用具有 bg 颜色的前一个单元格,因此您得到它是以前的设置。

一个提示是在这个方法中显式设置UIButtonUITableViewCell的背景颜色func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell ,因为每次它被重用时,颜色将被设置为默认值,你将不要获取之前重复使用的颜色。

刚设置

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  cell.backgroundColor = [UIColor whiteColor];
  cell.btnGetUpdates setBackgroundColor:[UIColor whiteColor];
//with along the other code, add these two lines.
}

编辑

为了获得像您想要的效果一样,设置一个实例变量,该变量存储所选单元格的 indexPath 类似 int 的内容。

在按钮操作方法中,将 int 存储到 button.tag 属性中,该属性也是单元格的 indexpath.row 属性。

在你的cellForRowAtIndexPath方法中,做一个检查

if(indexpath.row == selectedIntIndexPath){
  //change the colour whatever you want.
}

最后在按钮的IBAction方法中调用[self.tableView reloadData]

所以完整的代码将是这样的

@implementation ViewController{
int selectedIntIndexPath;
}

 -(IBAction)actionForButton:(id)sender{
UIButton *btn = (UIButton *)sender;
selectedIntIndexPath = btn.tag;
[self.customTableView reloadData];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UICustomTableViewCell *cell = (UICustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"reuseIdentifire" forIndexPath:indexPath];
if(indexPath.row == selectedIntIndexPath){
    // do your colour
  }
 return cell;
}

在 GetUpdatesButton() 函数内,将 indexPath.row 值的标志值保留在单独的数组中。 然后重新加载表格视图的特定单元格。

现在在 cellForRowAtIndexPath 函数中设置检查标志值是否设置的条件,如果设置,则更改背景颜色,否则设置默认颜色。

附注。 有不同种类的变通办法来解决这个问题。 只需了解逻辑并选择在代码中有用的逻辑即可。

这是我的解决方案,为了扩展@RaymondLedCarasco 评论:

在 Swift 4 Xcode 9.3 中测试

声明一个属性:

var numberCells: [Int] = []

单击单元格按钮时:

self.numberCells.append(indexPath.row)

在 CellForRowAtIndex 检查中:

if self.numberCells.contains(indexPath.row) { ... } else { ... }

在这里,我解决了大部分 TableViewCell 问题,例如在滚动剩余行后单击单元格按钮时可能会更改,以及在didSelectRowAt indexPath: IndexPath处选择行时,滚动剩余行后可能会被选中。 所以我创建了一个应用程序来解决这些问题。 这里添加GitHub代码找到代码

  • 在第一个屏幕中,单击一个红色按钮并向下滚动,您无法在 UITableViewCell 中看到其他单元格自动受到影响。

  • 单击第一个屏幕中的didSelectRowAt indexPath: IndexPath您可以转到第二个屏幕的详细信息屏幕,在该屏幕中选择一行后不会在 UITableViewCell 中自动选择其他行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM