【问题标题】:Strange behavior with UICollectionView cell selectionUICollectionView 单元格选择的奇怪行为
【发布时间】:2017-01-26 06:42:47
【问题描述】:

我目前有这个(伪)代码:

var selectedCell: UICollectionViewCell?

override func viewDidLoad() {
    super.viewDidLoad()
    ...
    #initialize all objects and pull data from the server to fill the cells

    UIView.animate(withDuration: 0, animations: {
        self.dataCollectionView.reloadData()
    }, completion: {(finished) in

        let indexPath = IndexPath(row: 0, section: 0)
        self.dataCollectionView.selectItem(at: indexPath, animated: true, scrollPosition: .top)
        self.collectionView(self.dataCollectionView, didSelectItemAt: indexPath)
    })
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! DataCollectionViewCell
    if !selectedCell {
        cell.layer.borderWidth = 1
    }
    else {
       cell.layer.borderWidth = 2            
    }
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAtindexPath: IndexPath) {

    let cell = collectionView.cellForItem(at: indexPath)
    selectedCell = cell
    cell.image = SomeImageFromServer
    cell.layer.borderWidth = 2
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {

    let cell = collectionView.cellForItem(at: indexPath)
    cell.layer.borderWidth = 1
}

我的想法是,此代码将在集合视图加载后立即选择第一个单元格,并且确实如此。问题是它也选择了最后一个单元格,但是从不为最后一个单元格调用 didSelectItemAtindexPath,而只为第一个单元格调用。

我尝试使用let indexPath = IndexPath(row: 1, section: 0) 选择第二个单元格,并且在加载集合视图后它确实选择了第二个单元格,并且没有像您想象的那样选择最后一个单元格。

一旦选择了任何一个单元格,最后一个单元格就会被取消选中。

所以我的假设是,这不是认为单元格被“选中”的代码,而是出于某种原因给选中的单元格一个“选中的单元格边框”,但前提是第一个选中的单元格是第一个选中的单元格。有什么想法吗?

【问题讨论】:

    标签: ios swift uicollectionview


    【解决方案1】:

    尝试将边框设置移动到单元格中,UICollectionView 会自动管理边框宽度:

    //Swift3
    class TestCollectionViewCell: UICollectionViewCell {
    
        override func awakeFromNib() {
            super.awakeFromNib()
    
            self.layer.borderWidth = 1 //Default border width
        }
    
        override var isSelected: Bool {
            didSet{
                if self.isSelected {
                    self.layer.borderWidth = 2
                }
                else{
                    self.layer.borderWidth = 1
                }
            }
        }
    }
    

    【讨论】:

    • 这是处理单元格选择的好方法,但它仍然不能修复最后一个单元格被“选中”
    • @Butterfly_123,去掉“self.collectionView(self.dataCollectionView, didSelectItemAt: indexPath)”这一行,“didSelectItemAt”委托方法仅用于处理用户触摸事件。如果以编程方式调用它可能会导致问题。如果应用我的解决方案,请删除控制器中的所有borderWidth设置代码。
    • 问题在于,一旦加载视图,我需要选择集合视图的第一个单元格。我已经使用您的实现从我的代码中删除了所有边框宽度属性。我在上面的代码中没有提到的是,我实际上也有一个单元格的覆盖层,并且使用 UIView 并将其作为子视图添加到单元格中。您知道将其添加到 UICollectionViewCell 的方法吗?另外,在加载视图后如何选择第一个单元格?
    • @Butterfly_123,不需要 UIView.animate 方法。加载视图后,“selectItem”方法应该足以选择第一个单元格。
    • 我这样做是因为 UIView.animate 用于捕获 reloadData 的结尾。如果我不这样做,它会给我一个索引路径错误。
    猜你喜欢
    • 1970-01-01
    • 2013-01-29
    • 2019-12-31
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-14
    • 1970-01-01
    相关资源
    最近更新 更多