使用 selectedBackgroundView 显示高亮状态

Posted

技术标签:

【中文标题】使用 selectedBackgroundView 显示高亮状态【英文标题】:Using selectedBackgroundView to show the highlighted state 【发布时间】:2015-01-05 03:43:24 【问题描述】:

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

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

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

【问题讨论】:

使用带有 UILabel 的常规 UICollectionViewCell 而不是 UIButton,然后简单地更改单元格的 contentView 的 backgroundColor 会有什么不同?您的按钮似乎没有做任何特别的事情,请注意集合或表格视图单元格内的按钮延迟其触地动画/突出显示,因为单元格本身首先被检查选择事件。 @Matt 确实该按钮并不特殊,它存在的唯一原因是因为 UICollectionViewCell 不是 UIControl 因此您无法检测到 TouchDown、TouchDragEnter、TouchCancel 等,所以没有触摸时改变外观的方法。当它被点击 (didSelectItemAtIndexPath) 但没有被触摸时,你可以。 【参考方案1】:

您不需要集合视图单元格内的按钮来设置它被按下时的突出显示颜色。只需将您的单元格的 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 中的单元格。 “按住不放”会自动为你处理,只有当用户抬起手指时才会触发取消选择动画。

我认为这很脏,因为每次将单元格出列以在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)

【讨论】:

如果我错了,请纠正我,但 selectedBackgroundView 只有在您以编程方式设置 selected = true 时才会显示,不是吗?因此,当您触摸单元格时,不会导致该视图出现。 啊,但是当你点击集合视图单元格时,selected 变为 true——无需在代码中设置它。 :) 我将编辑我的答案以提供更简洁的版本... 这很好用,可能是比我找到的更好的解决方案!【参考方案2】:

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

只需实现几个UICollectionViewDelegate 方法:collectionView:didHighlightItemAtIndexPath:collectionView:didUnhighlightItemAtIndexPath:。将backgroundView 属性变为突出显示时更改它,然后在它变为未突出显示时将其设置回nil

【讨论】:

你不应该每次按住单元格时都更改backgroundView——当单元格未选择时,该属性应该是背景视图,即它的正常状态。

以上是关于使用 selectedBackgroundView 显示高亮状态的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 13 上构建时,UITableViewCell selectedBackgroundView 的颜色不可见

ios自定义UITableviewCell选择的背景颜色没有SelectedBackgroundView

UITableView - 自定义 UITableViewCell 中的自定义 selectedBackgroundView 选择时隐藏单元格分隔符

带有自定义 selectedBackgroundView 的 UITableViewCell,它比 UISplitViewController 上的主视图控制器更宽

解决设置selectedBackgroundView后会把cell上带背景颜色的控件遮住的问题

设置 cell点击 背景色