简体   繁体   English

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

[英]Button action in custom UITableViewCell affects other cells

I have a TablewView that has prototype UITableViewCell that has its own class,我有一个TablewView ,它的原型UITableViewCell有自己的类,

Custom UITableViewCell Class自定义 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
    }

}

The TableView loads perfectly and the dataSource and delegate work fine. TableView 加载完美,数据源和委托工作正常。 However, when I click a BUTTON at IndexPath.row = 0 (zero), and then I scroll down , I would see random(?) or other cells also being highlighted as a result of clicking BUTTON in row 0...但是,当我单击 IndexPath.row = 0(零)处的 BUTTON,然后向下滚动时,由于单击第 0 行中的 BUTTON,我会看到随机(?)或其他单元格也被突出显示...

Here is my CellForRowAtIndexPath code:这是我的 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
        
    }

in my cell.btnGetUpdates , I put an action as you can see in the last part of my CellForIndex code, GetUpdatesButton:在我的cell.btnGetUpdates 中,我在 CellForIndex 代码的最后一部分GetUpdatesButton 中放置了一个操作

This is the code:这是代码:

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()
    }

The problem is, NOT ONLY the button in index 0 is being highlighted, but I would also see random buttons from other index/rows being highlighted as I scroll my tableView down.问题是,不仅索引 0 中的按钮被突出显示,而且当我向下滚动 tableView 时,我还会看到来自其他索引/行的随机按钮被突出显示。

Where did I go wrong, how can I only update the button I clicked...and not other buttons..我哪里出错了,我怎么能只更新我点击的按钮......而不是其他按钮......

I have 20 items ( 20 rows) and when I clicked button in row 0, rows 3, 6, 9....are also having highlighted buttons.我有 20 个项目(20 行),当我单击第 0 行中的按钮时,第 3、6、9 行......也有突出显示的按钮。

ROW 0 , button clicked第 0 行,单击按钮

第零行,单击按钮

ROW 3, button clicked as well, though I did not really click it.第 3 行,按钮也被点击了,虽然我并没有真正点击它。 在此处输入图片说明

This is occurring due to UITableview have reusablecell policy.In order to resolve this issue You need to maintain one array of selected items in cellForRowAtIndexPath method you have to verify weather this button is being hold by selected item array.这是由于 UITableview 具有可重用单元策略而发生的。为了解决此问题,您需要在 cellForRowAtIndexPath 方法中维护一组选定项目,您必须验证该按钮是否被选定项目数组保持。 if yes then apply selection styles otherwise apply normal style to it.如果是,则应用选择样式,否则对其应用普通样式。

Check below source code for buttonclick:检查下面的 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)
}

Below code for applying styles on buttons in CellForRowAtIndexPath:以下代码用于在 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

} }

I hope this helps to resolve your problem!我希望这有助于解决您的问题! Thanks.谢谢。

This is because cells are being reused.这是因为细胞正在被重用。 So when you colour the cells using the button action, the cell's background is being painted which i guess is working fine but the situation is that when you scroll up or down, the previous cell which is having bg colour is being reused and hence you get the previous settings it was.因此,当您使用按钮操作为单元格着色时,单元格的背景正在被绘制,我猜这工作正常,但情况是当您向上或向下滚动时,正在重用具有 bg 颜色的前一个单元格,因此您得到它是以前的设置。

A tip would be to explicitly set the background colour of the UIButton and UITableViewCell in this method func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell , as everytime it will be reused the colour will be set as default and you will NOT get the previous colour it was being reused from.一个提示是在这个方法中显式设置UIButtonUITableViewCell的背景颜色func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell ,因为每次它被重用时,颜色将被设置为默认值,你将不要获取之前重复使用的颜色。

Just set刚设置

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.
}

EDIT编辑

for getting an effect like you want set an instance variable which stores the indexPath of the selected Cell something like an int.为了获得像您想要的效果一样,设置一个实例变量,该变量存储所选单元格的 indexPath 类似 int 的内容。

In the button action method store the int to the button.tag property which is also the indexpath.row property of the cell.在按钮操作方法中,将 int 存储到 button.tag 属性中,该属性也是单元格的 indexpath.row 属性。

in your cellForRowAtIndexPath method, do a check在你的cellForRowAtIndexPath方法中,做一个检查

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

Finally in the IBAction Method of the button call [self.tableView reloadData]最后在按钮的IBAction方法中调用[self.tableView reloadData]

So the complete code will be something like this所以完整的代码将是这样的

@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;
}

Inside the GetUpdatesButton() function , keep a flag value for the indexPath.row value in a separate array.在 GetUpdatesButton() 函数内,将 indexPath.row 值的标志值保留在单独的数组中。 Then reload the specific cell of the table view.然后重新加载表格视图的特定单元格。

Now in the cellForRowAtIndexPath function make a condition of checking the flag value is set or not, If set then change background colour else set the default colour.现在在 cellForRowAtIndexPath 函数中设置检查标志值是否设置的条件,如果设置,则更改背景颜色,否则设置默认颜色。

PS.附注。 there are different kinds of work arounds to solve the issue.有不同种类的变通办法来解决这个问题。 Just understand the logic and go for the one which is useful in the code.只需了解逻辑并选择在代码中有用的逻辑即可。

Here my solutions, in order to expand @RaymondLedCarasco comment:这是我的解决方案,为了扩展@RaymondLedCarasco 评论:

Tested in Swift 4 Xcode 9.3在 Swift 4 Xcode 9.3 中测试

Declare a propierty:声明一个属性:

var numberCells: [Int] = []

When click the button of Cell:单击单元格按钮时:

self.numberCells.append(indexPath.row)

In CellForRowAtIndex check:在 CellForRowAtIndex 检查中:

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

Here most of TableViewCell problems I have solved, Like when clicking the cell button after scrolling the remaining rows may be changed and when selecting at didSelectRowAt indexPath: IndexPath the row, after scrolling the remaining rows may be selected.在这里,我解决了大部分 TableViewCell 问题,例如在滚动剩余行后单击单元格按钮时可能会更改,以及在didSelectRowAt indexPath: IndexPath处选择行时,滚动剩余行后可能会被选中。 So I created an app to solve those problems.所以我创建了一个应用程序来解决这些问题。 Here adding GitHub code Find the code这里添加GitHub代码找到代码

  • In the first screen, click on a red button and just scroll down you can't see other cells are affected automatically in UITableViewCell.在第一个屏幕中,单击一个红色按钮并向下滚动,您无法在 UITableViewCell 中看到其他单元格自动受到影响。

  • Clicking on didSelectRowAt indexPath: IndexPath in the first screen you can go to details screen that's the second screen, in that screen after selecting a row other rows won't be selected automatically in UITableViewCell.单击第一个屏幕中的didSelectRowAt indexPath: IndexPath您可以转到第二个屏幕的详细信息屏幕,在该屏幕中选择一行后不会在 UITableViewCell 中自动选择其他行。

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

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