我想更改图像在 UICollectionView 中点击时,实际上图像正在改变,但不在正确的位置

I Want to change An Image On tap in UICollection View, Actually Image is Changing, But Not At right Place

我正在尝试在 collection 视图中点击更改 selected 和 unselected 图像,但是如果我 select 但是从第一个索引开始反映在其他指数中。我一次只想要一个 selection,但它也反映在其他部分。

这是我的 collection 视图结构。

struct teamSelected {
    var logoImage: String
    var isImageSelected: Bool 
}

我为 currentIndex

创建了一个变量
var currentIndex : Int = 0

我的 collection 视图的数据如下所示:

var teamSelectionList: [teamSelected] = [
    teamSelected(logoImage: "ic_team_yellow_big", isImageSelected: false),
    teamSelected(logoImage: "ic_team_red_big", isImageSelected: false),
    teamSelected(logoImage: "ic_team_purple_big", isImageSelected: false),
    teamSelected(logoImage: "ic_team_blue_big", isImageSelected: false),
    teamSelected(logoImage: "ic_team_green_big", isImageSelected: false),
    teamSelected(logoImage: "ic_team_orange_big", isImageSelected: false)
]

这是我的 collection 查看方法:

extension TeamViewController : UICollectionViewDelegate , UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return  teamSelectionList.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let teamSelection : TeamSelectionCollectionViewCell = self.teamCollectionView.dequeueReusableCell(withReuseIdentifier: "teamCell", for: indexPath) as! TeamSelectionCollectionViewCell
        let row = teamSelectionList[indexPath.row]
        teamSelection.logoImage.image = UIImage(named: row.logoImage)
        teamSelection.logoButton.isSelected = row.isImageSelected
        //teamSelection.logoButton.layer.setValue(row, forKey: "index")
        
        
        teamSelection.logoButton.tag = indexPath.row
        teamSelection.logoButton.addTarget(self, action: #selector(logoButtonTapped), for: .touchUpInside)
        teamSelection.seperatorView.isHidden = indexPath.row == 2 || indexPath.row == self.teamSelectionList.count - 1 ? true : false
        
        
        
        return teamSelection
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
        return CGSize(width: (teamCollectionView.frame.width / 3), height: 110.0)
    }
    
    
    @objc func logoButtonTapped(sender: UIButton){
        
       // self.teamSelectionList[sender.tag].isImageSelected = true
     //   self.teamSelectionList[self.currentIndex].isImageSelected = self.currentIndex != sender.tag ? false : true

        self.currentIndex = sender.tag
        if (teamSelectionList[self.currentIndex].isImageSelected == false){
            teamSelectionList[self.currentIndex].isImageSelected = true
            sender.setImage(UIImage(named: "ic_radio_selected"), for: UIControl.State.normal)
        } else {
            teamSelectionList[self.currentIndex].isImageSelected = false
            sender.setImage(UIImage(named: "ic_radio_normal"), for: UIControl.State.normal)
        }
        self.teamCollectionView.reloadData()
    }
}

这是我得到的输出:

您在点击后使用 sender.setImage 更新选择图像。集合视图重复使用单元格,不能保证在下一个布局中使用相同的单元格。

我建议您将其从 logoButtonTapped 移至 cellForItemAt,例如:

teamSelection.logoButton.isSelected = row.isImageSelected
teamSelection.logoButton.setImage(
    UIImage(named: row.isImageSelected ? "ic_radio_normal" : "ic_radio_selected"),
    for: UIControl.State.normal
)

还有一些提示。

  1. 根据 swift 代码风格指南,类 和结构的名称以大写字母开头并使用驼峰式大小写,例如struct TeamSelected 而不是 struct teamSelected。当您了解您是在调用函数还是 class/struct 构造函数时,阅读起来会容易得多。
  2. 存储选定的索引比存储每个项目的选择状态要容易得多。它需要更少的代码并降低错误概率。您的代码可以这样更新:
class TeamViewController: UIViewController {
    let teamLogoList = [
        "ic_team_yellow_big",
        "ic_team_red_big",
        "ic_team_purple_big",
        "ic_team_blue_big",
        "ic_team_green_big",
        "ic_team_orange_big",
    ]
    var selection = Set<Int>()
}

extension TeamViewController : UICollectionViewDelegate , UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return teamLogoList.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let teamSelection : TeamSelectionCollectionViewCell = self.teamCollectionView.dequeueReusableCell(withReuseIdentifier: "teamCell", for: indexPath) as! TeamSelectionCollectionViewCell
        let index = indexPath.row
        teamSelection.logoImage.image = UIImage(named: teamLogoList[index])
        let isImageSelected = selection.contains(index)
        teamSelection.logoButton.isSelected = isImageSelected
        teamSelection.logoButton.setImage(
            UIImage(named: isImageSelected ? "ic_radio_normal" : "ic_radio_selected"),
            for: UIControl.State.normal
        )
        //teamSelection.logoButton.layer.setValue(row, forKey: "index")

        teamSelection.logoButton.tag = indexPath.row
        teamSelection.logoButton.addTarget(self, action: #selector(logoButtonTapped), for: .touchUpInside)
        teamSelection.seperatorView.isHidden = indexPath.row == 2 || indexPath.row == self.teamLogoList.count - 1 ? true : false



        return teamSelection
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
        return CGSize(width: (teamCollectionView.frame.width / 3), height: 110.0)
    }


    @objc func logoButtonTapped(sender: UIButton){
        let index = sender.tag
        if (selection.contains(index)){
            selection.remove(index)
        } else {
            selection.insert(index)
        }
        self.teamCollectionView.reloadData()
    }
}