使用 selectedBackgroundView 显示高亮状态

Using selectedBackgroundView to show the highlighted state

想象一下您有一个 UICollectionView 并且在每个单元格中您希望有一个按钮填充整个单元格的场景,以便您可以响应各种触摸事件来处理高亮外观。例如,当用户按下按钮时,您想要更改按钮的背景颜色,然后在他们拖出或取消触摸等时恢复它。现在想象一下这种情况,您不想更改按钮的背景颜色,而是要更改按钮的背景颜色单元格的 backgroundViewUIButton 没有背景视图,只有 backgroundColorbackgroundImage.

我有一个解决方案,但我想知道如果不推荐这种方法,它是否可以更清洁。触摸按钮后,我循环遍历它的 superviews 直到我得到 UICollectionViewCell,然后我将它的 selected 属性设置为 true。在 cellForItemAtIndexPath 中,我根据需要设置了 selectedBackgroundView。这样得到了想要的行为,但是用selected state来表示highlight state,这样管理是不是不合适?什么会更好?

我可以在触摸按钮时获得 UICollectionViewCell 然后更改其 backgroundView 属性而不是在创建每个单元格时这样做,那么就不需要更改 selected价值。但这仍然不是一个很好的解决方案。

您不需要集合视图单元格内的按钮来设置其按下时的突出显示颜色。只需将您的单元格的 selectedBackgroundView 设置为与您的单元格具有相同宽度和高度的视图,并为该视图提供您想要突出显示该单元格的 backgroundColor

我做的一个(肮脏的)实现是这样的:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CELL", forIndexPath: indexPath) as UICollectionViewCell
    cell.selectedBackgroundView = {
        let bgview = UIView(frame: CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height))
        bgview.backgroundColor = UIColor.redColor()
        return bgview
    }()
    return cell
}

然后,只需取消选择 didSelectItemAtIndexPath 中的单元格。 "holding downpress"会自动为你处理,取消选择动画只会​​在用户抬起手指时触发。

我认为这很脏,因为每次单元格出列以便在 cellForItemAtIndexPath: 中重新使用时,您都在设置 selectedBackgroundView。我要做的是创建一个 UICollectionViewCell 子类,从那里设置它的 selectedBackgroundView,然后在集合视图上使用 registerNib:registerClass: 注册该单元格。


添加:更清洁的版本。在您的自定义集合视图单元子类中,分配 backgroundViewselectedBackgroundView:

override init(frame: CGRect) {
    super.init(frame: frame)

    self.backgroundView = {
        let view = UIView()
        view.backgroundColor = UIColor.yellowColor()
        return view
    }()

    self.selectedBackgroundView = {
        let view = UIView()
        view.backgroundColor = UIColor.redColor()
        return view
        }()
}

以及您的视图控制器、集合视图数据源和委托中的相关方法:

override func viewDidLoad() {
    super.viewDidLoad()
    self.collectionView.registerClass(NSClassFromString("test.CustomCollectionViewCell"), forCellWithReuseIdentifier: "CELL")
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CELL", forIndexPath: indexPath) as UICollectionViewCell
    return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    collectionView.deselectItemAtIndexPath(indexPath, animated: true)
}

我找到了一个非常干净的解决方案。 UICollectionViewCells 已经有一个突出显示的状态,可以自动跟踪发生的各种触摸事件。然而,没有 highlightedBackgroundView 就像有 selectedBackgroundView,但您仍然可以利用突出显示状态来修改单元格在突出显示和取消突出显示时的外观。因此,无需在每个单元格中使用 UIButton - UILabel 就可以了。

只需实施几个 UICollectionViewDelegate 方法:collectionView:didHighlightItemAtIndexPath:collectionView:didUnhighlightItemAtIndexPath:。当 backgroundView 属性 高亮时更改它,然后在它不高亮时将其设置回 nil