确保在UICollectionView中只有1个单元格具有活动状态

时间:2018-06-05 21:19:56

标签: ios swift uicollectionview

我有一个UICollectionView,其中我只希望1个单元格处于活动状态。活跃的意思是:已经点击的最后一个单元格(或者收集视图放置时的第一个单元格)。当用户单击非活动单元格时,我想将旧的活动单元格重置为非活动单元格。我这样做有困难。这是因为visibleCells是集合视图的属性,它只返回屏幕上的单元格而不返回内存中的单元格。这是我目前查找活动单元格并将状态重置为非活动状态的方法。

这种情况可能发生,导致多个活动单元格:用户稍微向下滚动,以便当前活动单元格不再可见,点击随机单元格并向上滚动。问题是旧的活动单元格保留在内存中,尽管它不可​​见:cellForItemAt(_:)不会被调用该单元格。坏消息是,visibleCells也找不到旧的活动单元格。我该怎么找到它?函数willDisplay cell也不起作用。

可以将示例项目直接克隆到xCode:https://github.com/Jasperav/CollectionViewActiveIndex

这是示例项目中的代码:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var collectionView: CollectionView!
    static var activeIndex = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.go()
    }
}

class Cell: UICollectionViewCell {
    @IBOutlet weak var button: MyButton!

}

class CollectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource {
    func go() {
        delegate = self
        dataSource = self
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

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

    internal func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell
        if indexPath.row == ViewController.activeIndex {
            cell.button.setTitle("active", for: .normal)
        } else {
            cell.button.setTitle("not active", for: .normal)
        }
        cell.button.addTarget(self, action: #selector(touchUpInside(_:)), for: .touchUpInside)
        return cell
    }

    @objc private func touchUpInside(_ sender: UIButton){
        let hitPoint = sender.convert(CGPoint.zero, to: self)
        guard let indexPath = indexPathForItem(at: hitPoint), let cell = cellForItem(at: indexPath) as? Cell else { return }

        // This is the problem. It does not finds the current active cell
        // if it is just out of bounds. Because it is in memory, cellForItemAt: does not gets called
        if let oldCell = (visibleCells as! [Cell]).first(where: { $0.button.titleLabel!.text == "active" }) {
            oldCell.button.setTitle("not active", for: .normal)
        }

        cell.button.setTitle("active", for: .normal)

        ViewController.activeIndex = indexPath.row
    }

}

2 个答案:

答案 0 :(得分:1)

要从这个小故障中恢复,您可以尝试cellForRowAt

cell.button.tag = indexPath.row

单击按钮时

ViewController.activeIndex = sender.tag
self.reloadData()

答案 1 :(得分:0)

您可以使用isSelected的{​​{1}}属性。如果选中,则可以为单元格设置活动布局。选择机制默认在UIColectionViewCell中实现。如果要选择/激活多个单元格,可以将属性UIColectionViewCell设置为true。

基本上这种方法看起来像这样:

allowsMultipleSelection