How to access buttons in a UICollectionView from a

2019-07-29 06:51发布

问题:

In my View Controller, I have a collection view that, when rendered, displays 3 cells, each of which has a label, and a button. The label displays the name of a color, and the button has a background image that displays a color swatch.

I want it so that whenever you click on one of the buttons, that button gets a dark border around it, while the other buttons get a light border on them, to indicate the clicked-on button as being "selected". Alternately, I could probably do this by changing the image out based on the selected state of the image - but my question remains the same.

How do I access the other two buttons, to toggle their properties?

I have a script implemented that allows me to add a border to the button that somebody clicked on - but I cannot figure out how to access the other buttons, in the other cells of the CollectionView to alter their border properties as well.

Here is my source code (with irrelevant/unrelated bits stripped out)

class trimSelectorVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var trimSelector: UICollectionView!

    struct trimObject {
        var trimName: String
        var trimButton: String
        var trimID: Int
    }

    var trimArray: [trimObject] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        trimArray.append(trimObject(trimName: "Chrome", trimButton: "chrome-swatch", trimID: 0))
        trimArray.append(trimObject(trimName: "Gold", trimButton: "gold-swatch", trimID: 1))
        trimArray.append(trimObject(trimName: "Gun Metal", trimButton: "gunmetal-swatch", trimID: 2))

        trimSelector.delegate = self
        trimSelector.dataSource = self
    }


    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return trimArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! trimSelectionCell

        //Set the label text
        cell.trimLabel.text = trimArray[indexPath.item].trimName

        //Set the image for the button
        cell.trimButton.setImage(UIImage(named: trimArray[indexPath.item].trimButton), for: UIControlState.normal)

        //Sets a target function for the button
        cell.trimButton.addTarget(self, action: #selector(selectedSwatch), for: .touchUpInside)

        return cell
    }


    func selectedSwatch(sender: UIButton) {

        //These set the "selected" border to the button you clicked on.
        sender.layer.borderWidth = 2
        sender.layer.borderColor = UIColor(red: 83/255, green: 71/255, blue: 65/255, alpha: 1.00).cgColor


    }
}

Can anybody please tell me how to access the other buttons in my "selectedSwatch" function?

回答1:

There are various ways you can handle this. A UICollectionView view has a method visibleCells() that returns an array of it's visible cells. You could use that to get pointers to your cells. You would need a way to figure out which one is which. You could use indexPath(for: UICollectionViewCell) to figure out the index path of each cell, for example.



回答2:

I don't know if this might help, but what about if you store the IndexPath on your struct on cellForItemAt method?

You will have:

struct trimObject {
    var trimName: String
    var trimButton: String
    var trimID: Int
    var idx : IndexPath
}

Then on:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! trimSelectionCell
            ....

 trimArray[indexPath.item].idx = indexPath
     .... 
}

And in your selectedSwatch method:

func selectedSwatch(sender: UIButton) {

    //These set the "selected" border to the button you clicked on.
    sender.layer.borderWidth = 2
    sender.layer.borderColor = UIColor(red: 83/255, green: 71/255, blue: 65/255, alpha: 1.00).cgColor

    if let cell = (sender.superview as? UICollectionViewCell) {

        //Cell with the button selected:
        let idx = collectionView.indexPath(for: cell)

        //array of the other objects:
        let allOtherObjects = trimArray.filter { ($0 as! trimObject).idx != idx }

        allOtherObject.forEach({ (trimObj) in
            let cell = collection.cellForItem(at: trimObj.idx)
            //Do whatever yo need to do...
            //cell.trimButton.layer
        })
    }

}


回答3:

Its may be to late but still useful for somebody Swift 4 version: You can use sender superview as UiCollectionViewCell * Consider hierarchy of sender in collection view cell

func selectedSwatch(sender: UIButton) {
   let cell = sender.superview?.superview as! trimSelectionCell
   //cell.yourbtn 
}


回答4:

Try this,

 class trimSelectorVC: UIViewController, UICollectionViewDelegate, 
 UICollectionViewDataSource {

@IBOutlet weak var trimSelector: UICollectionView!

struct trimObject {
    var trimName: String
    var trimButton: String
    var trimID: Int
    var isSelected : String
}

var trimArray: [trimObject] = []

override func viewDidLoad() {
    super.viewDidLoad()
    trimArray.append(trimObject(trimName: "Chrome", trimButton: "chrome-swatch", trimID: 0,isSelected : "0"))
    trimArray.append(trimObject(trimName: "Gold", trimButton: "gold-swatch", trimID: 1,isSelected : "0"))
    trimArray.append(trimObject(trimName: "Gun Metal", trimButton: "gunmetal-swatch", trimID: 2,isSelected : "0"))

    trimSelector.delegate = self
    trimSelector.dataSource = self
}


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return trimArray.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! trimSelectionCell

    //Set the label text
    cell.trimLabel.text = trimArray[indexPath.item].trimName

    //Set the image for the button
    cell.trimButton.setImage(UIImage(named: 
  trimArray[indexPath.item].trimButton), for: UIControlState.normal)
   if(trimArray[indexPath.item].isSelected == "0"){
   // button not clicked
  // change shadow color of button

    }
   else
    {
   // button  clicked
       cell.trimButton.layer.borderWidth = 2
      cell.trimButton.layer.borderColor = UIColor(red: 83/255, green: 
       71/255,blue: 65/255, alpha: 1.00).cgColor
    }
     // set tag to the button
     cell.trimButton.tag = indexPath.item 

    //Sets a target function for the button
    cell.trimButton.addTarget(self, action:#selector(selectedSwatch), 
         for: .touchUpInside)

     return cell
  }


func selectedSwatch(sender: UIButton) {

    //These set the "selected" border to the button you clicked on.

  let index = sender.tag
   for obj in trimArray {
   obj.isSelected = "0"
   }

   trimArray[index].isSelected = "1"

  collectionView.reloadData()
}

}