如何更改特定 TableViewCell 中的按钮颜色

Posted

技术标签:

【中文标题】如何更改特定 TableViewCell 中的按钮颜色【英文标题】:How to change Button color in specific TableViewCell 【发布时间】:2017-07-17 03:23:39 【问题描述】:

我有一个类似测验应用的应用。在 tableViewCell 中有 4 个用于任务变体的按钮。当用户按下按钮时,我需要更改颜色,当我尝试在按钮操作中更改颜色时,所有表格视图单元格中的按钮颜色都会发生变化。但我只需要在我按下的地方进行更改。我已经尝试过编写委托,但它给出的结果相同,这是我编写委托的代码:

class CustomButton: UIButton 

override var isHighlighted: Bool 
    didSet 
        if isHighlighted 
            backgroundColor = UIColor.lightGray
         else 
            backgroundColor = UIColor.init(red: 34/255, green: 89/255, blue: 128/255, alpha: 1.0)
        
    

我已经为按钮添加了目标动作。

var variant1 = UIButton()
var variant2 = UIButton()
var variant3 = UIButton()
var variant4 = UIButton()

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "finalCell")!
    variant1 = cell.contentView.viewWithTag(1) as! UIButton
    variant2 = cell.contentView.viewWithTag(2) as! UIButton
    variant3 = cell.contentView.viewWithTag(3) as! UIButton
    variant4 = cell.contentView.viewWithTag(4) as! UIButton


    if (numberOfVariants.count != 0) 
        let questionTextView = cell.contentView.viewWithTag(5) as! UITextView
        questionTextView.text = "\(Questions[indexPath.row].content!)"
        variant1.addTarget(self, action: #selector(self.variant1ButtonPressed), for: .touchUpInside)
        variant2.addTarget(self, action: #selector(self.variant2ButtonPressed), for: .touchUpInside)
        variant3.addTarget(self, action: #selector(self.variant3ButtonPressed), for: .touchUpInside)
        variant4.addTarget(self, action: #selector(self.variant4ButtonPressed), for: .touchUpInside)
          
        return cell
    

当用户点击按钮时,我已经确定了表格视图的 indexPath(如果有帮助的话):

    func variant1ButtonPressed(_ sender:AnyObject) 
    print("Variant1")
    let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
    let intIndexpath = Int((indexPath?.row)!)
    globalIndexPath = intIndexpath

func variant2ButtonPressed(_ sender:AnyObject) 
    let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
    let intIndexpath = Int((indexPath?.row)!)
    globalIndexPath = intIndexpath


func variant3ButtonPressed(_ sender:AnyObject) 
    let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
    let intIndexpath = Int((indexPath?.row)!)
    globalIndexPath = intIndexpath



func variant4ButtonPressed(_ sender:AnyObject) 
    let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
    let intIndexpath = Int((indexPath?.row)!)
    globalIndexPath = intIndexpath



这是它在故事板中的样子(如果有帮助)

【问题讨论】:

您需要在触摸按钮时更改颜色还是在选择时更改颜色? @ReinierMelian 当用户选择一个按钮时改变这个按钮的颜色。 你需要实现 isSelected 而不是 isHighlighted 属性来显示选择的颜色。 @Surjeet 我试过同样的问题。例如,当我在第一个单元格中按下第一个变体时,它会更改所有单元格中所有第一个变体的颜色 您需要将 selectedIndexPath 保存在一个变量中,并且在 cellForRowAt 函数中,您需要将 selectedIndexPath 与 indexPath 进行比较。如果两者相同,则只需要应用选定的颜色,否则应用普通颜色。 【参考方案1】:

我认为您使用的代码比执行此任务所需的代码多得多,因此这是使用closures 的另一种方法,我的情节提要中只有一个viewController,并在其中添加了一个UITableView 和一个名为ButtonTableViewCell 的customCell然后我将一个普通的 UIButton 作为@IBOutlet 链接到该单元格,仅此而已,完整的实现在这里

https://github.com/rmelian2014/SOButtonsTableViewCellQuestion

已编辑

ButtonTableViewCell

    import UIKit

@IBDesignable
class ButtonTableViewCell: UITableViewCell 

    @IBInspectable var selectedColor : UIColor = UIColor.red
    @IBInspectable var normalColor : UIColor = UIColor.blue

    static let cellHeigth : CGFloat = 360

    @IBOutlet var buttonsArray: [UIButton]!
    var selectedText : String?
        willSet
            guard newValue != nil else
                return
            

            var foundedIndex = -1
            for (index,text) in self.texts.enumerated() 
                if(text == newValue!)
                    foundedIndex = index
                    break
                
            

            guard foundedIndex != -1 else
            
                return
            

            self.buttonsArray[foundedIndex].backgroundColor = selectedColor
        
    
    var texts : [String] = []

    var buttonActionClosure : ((_ selectedText:String?)->Void)?

    func setupWithClosure(texts:[String],textSelected:String?,closure:((_ selectedText:String?)->Void)?)
    
        self.texts = texts

        for (index,button) in self.buttonsArray.enumerated()
            if(self.texts.count > index)
            
                button.setTitle(self.texts[index], for: .normal)
            
            button.tag = index
            button.backgroundColor = self.normalColor
        


        self.selectedText = textSelected
        if(closure != nil)
        
            self.buttonActionClosure = closure
        


    

    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
    

    @IBAction func buttonAction(sender:UIButton)
    
        if(self.texts.count > sender.tag)
            let newSelectedText = self.texts[sender.tag]

            if(newSelectedText != self.selectedText)
                self.selectedText = newSelectedText
            else
            
                self.selectedText = nil
            
        
        if(self.buttonActionClosure != nil)
        
            self.buttonActionClosure!(self.selectedText)
        
    

    override func prepareForReuse() 
        super.prepareForReuse()
        self.buttonActionClosure = nil
    


视图控制器

import UIKit

class ViewController: UIViewController 

    @IBOutlet weak var tableView: UITableView!

    var dictOfSelectedsCells : [Int:String?] = [:]

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        tableView.delegate = self
        tableView.dataSource = self
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    




extension ViewController : UITableViewDelegate,UITableViewDataSource

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 4
    

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        return ButtonTableViewCell.cellHeigth
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

        if let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonTableViewCell", for: indexPath) as? ButtonTableViewCell
        
            cell.selectionStyle = .none
            var selectedText : String?
            if let currentSelectedText = self.dictOfSelectedsCells[indexPath.row]
            
                selectedText = currentSelectedText
            

            cell.setupWithClosure(texts:["Variant1","Variant2","Variant3","Variant4"], textSelected: selectedText, closure:  [weak self] (selected) in
                debugPrint(indexPath)
                self?.dictOfSelectedsCells[indexPath.row] = selected
                tableView.reloadRows(at: [indexPath], with: .none)
            )

            return cell
        
        assert(false, "this must not happen")
    

希望对你有帮助

【讨论】:

@АзаматБулегенов 不,您只需在情节提要中定义您的 customCell,如果您愿意,我可以发布图片来帮助您 它工作我试过谢谢。但是你能把你的代码编辑成 4 个按钮吗 @АзаматБулегенов 检查 repo github.com/rmelian2014/SOButtonsTableViewCellQuestion 并测试它,最好的问候 我想你没明白我的意思,一个单元格中应该有 4 个按钮 您可以使用部分,但我可以修改我的代码@АзаматБулегенов【参考方案2】:

在您的 cellForRowAt indexPath: 方法中,您需要检查该行的 indexpath 是否与所选按钮的 indexpath 相同。如果相同,则需要显示突出显示的颜色,否则显示正常颜色。

所以将按下的按钮的索引路径保存在您的 buttonpressed 方法中的全局变量中。让变量被选中ButtonIndexPath。

在您的 cellForRowAt indexPath: 方法中添加以下代码

 if indexPath.row==selectedButtonIndexPath.row 
        backgroundColor = UIColor.lightGray
     else 
        backgroundColor = UIColor.init(red: 34/255, green: 89/255, blue: 128/255, alpha: 1.0)
    

当然,当单击按钮以反映颜色的变化时重新加载您的表格视图。

更新 1:

您能否尝试通过获取 sender.tag 在您的按钮按下方法中保存按钮的标签,然后更改您的 if 条件

if indexPath.row==selectedButtonIndexPath.row  
    if buttonTag == 1
        variant1.backgroundcolor = UIColor.lightGray
        variant2.backgroundColor = UIColor.init(red: 34/255, green: 89/255, blue: 128/255, alpha: 1.0)
        // and so on for all buttons.
    else if buttonTag == 2
        // same as above but for variant2
    
 else 


【讨论】:

我创建了全局变量 selectedButtonIndexPath 并将其等同于选定的按钮 indexpath 并将您编写的函数添加到 cellForRowAt 函数它不起作用。 好的,现在尝试理解这里的场景。您的每个单元格都有 4 个按钮变体 1-4。而且您的表格视图中是否还有多个单元格,每个单元格都有 4 个按钮?因为现在您的代码 deos 仅更改所选单元格的变体 1 的颜色。这是你想要达到的目标吗? 只是变体 1 只是对我的完美测试,我按下的按钮无关紧要,第一个或第四个按钮必须改变颜色。我刚刚编写了变体 1 进行测试,但它不起作用 你能解释一下是什么场景吗? globalIndexPath 将给出已单击的单元格,而不是在这种情况下的按钮。因此,除了保存之外,您还必须保存单击的按钮变体,然后您的 if 条件应该同时检查单元格索引路径和变体类型。 您可以按照 Reinier 提到的以下注释或在您现有的代码中,当您保存 globalIndexPath 时,保存所选按钮的标记,然后修改 if 语句以检查哪个标签被点击并改变它的颜色。因此必须进行 2 次检查。首先是使用索引路径单击的单元格,然后是被单击按钮的标记

以上是关于如何更改特定 TableViewCell 中的按钮颜色的主要内容,如果未能解决你的问题,请参考以下文章

使用委托使用按钮更改 tableViewCell 内 UITextField 的值

按下 tableViewCell 中的按钮时打开一个新的 VC

在swift 3中的tableview中更新tableviewcell中的特定行?

我无法将 TableViewCell 按钮连接到 TableViewController!如何将 TableViewCell 中的值连接到 TableViewController?

MVVMCross iOS如何在TableViewCell按钮中传递参数

如何从自定义 tableviewcell 中的按钮显示弹出视图?