ios 点击更改 UICollectionView 单元格的背景

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23392485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:03:00  来源:igfitidea点击:

Change Background of UICollectionView Cell on Tap

iosobjective-cuicollectionviewuicollectionviewcelluicollectionviewdelegate

提问by jac300

I have a UICollectionView that I have created programmatically. I would like for the collection view to behave in the following way:

我有一个以编程方式创建的 UICollectionView。我希望集合视图按以下方式运行:

1. User touches cell
2. Cell background color changes
3. User releases touch
4. Cell background color changes

This should be a quick color change that happens just before the selector related to the tap action is executed in which the viewcontroller containing the collection view is popped off the stack.

这应该是在执行与点击操作相关的选择器之前发生的快速颜色更改,其中包含集合视图的视图控制器从堆栈中弹出。

I have been looking at this question: UICollectionView cell change background while tap

我一直在看这个问题:UICollectionView cell change background while tap

in which there is the following summary of methods to use for this purpose:

其中有以下用于此目的的方法摘要:

// Methods for notification of selection/deselection and highlight/unhighlight events.
// The sequence of calls leading to selection from a user touch is:
//
// (when the touch begins)
// 1. -collectionView:shouldHighlightItemAtIndexPath:
// 2. -collectionView:didHighlightItemAtIndexPath:
//
// (when the touch lifts)
// 3. -collectionView:shouldSelectItemAtIndexPath: or -    collectionView:shouldDeselectItemAtIndexPath:
// 4. -collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:
// 5. -collectionView:didUnhighlightItemAtIndexPath:

I am assuming I only need to implement one of the above methods from 'when touch begins' and 'when touch ends.' But no matter what I do, it appears that a background color changes and then remains changed. Here is an example of something I attempted which did not work:

我假设我只需要从“触摸开始时”和“触摸结束时”实现上述方法之一。但无论我做什么,似乎背景颜色都会发生变化,然后保持变化。这是我尝试过但不起作用的示例:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
 {
   //pop vc 
 }

- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor redColor];
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

This results in the cell background color being changed only to red. I also looked at this question: UICollectionView Select and Deselect issueand tried implementing [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] and calling it inside of didSelectItemAtIndexPath, but this did not work either. Collection view data source and delegate are set.

这会导致单元格背景颜色仅更改为红色。我还查看了这个问题:UICollectionView Select and Deselect issue并尝试实现 [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] 并在 didSelectItemAtIndexPath 中调用它,但这也不起作用。集合视图数据源和委托已设置。

回答by Antonio E.

The problem is that you are changing the color on highlightand changing it back on deselectinstead that on unhighlight

问题是,你正在改变颜色的亮点,改变它放回取消而不是在unhighlight

You should simply change this:

你应该简单地改变这个:

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

to this:

对此:

- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

Also, if you don't want to wait a bit before getting your highlight happen you should set the delaysContentTouchesproperty of the collection view to NO

此外,如果您不想在突出显示之前稍等片刻,您应该将delaysContentTouches集合视图的属性设置为NO

Edit: also ensure that you call

编辑:还要确保你打电话

[collectionView deselectItemAtIndexPath:indexPath animated:NO];

inside the -didSelectItemAtIndexPath method

在 -didSelectItemAtIndexPath 方法中

回答by Suragch

Swift 3 version

斯威夫特 3 版本

Add the following two methods to your view controller class:

将以下两个方法添加到您的视图控制器类:

// change background color when user touches cell
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.red
}

// change background color back when user releases touch
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.green
}

See herefor help in setting up a basic collection view in Swift.

有关在 Swift 中设置基本集合视图的帮助,请参见此处

回答by Abirami Bala

Edit: Answer in Swift 3

编辑:在 Swift 3 中回答

var selectedIndex = Int ()

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell

    cell.backgroundColor = selectedIndex == indexPath.row ? UIColor.green : UIColor.red

    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
    selectedIndex = indexPath.row

    self.yourCollctionView.reloadData()
}

回答by DawnSong

Here is my solution. And I'm sure it really works.
I provide three methods to highlight a cell (selectedBackgroundView, tint cell.contentViewand tint a special area).

这是我的解决方案。而且我确信它确实有效。
我提供了三种方法来突出显示单元格(selectedBackgroundView、tintcell.contentView和 tint a special area)。

How to use:
1. just inherit BaseCollectionViewCelland do nothing;
2. inherit and set specialHighlightedArea = UIView(), and contentView.addSubView(specialHighlightedArea), then layout it or add constraint to use Auto Layout;
3. if you don't need highlight effect, just write a method named 'shouldHighlightItemAtIndexPath' defined by UICollectionViewDelegateand make it return false, or set cell.shouldTintBackgroundWhenSelected = falseand set specialHighlightedArea = niland remove it from superView.

使用方法:
1. 只是继承BaseCollectionViewCell,什么都不做;
2.继承并设置specialHighlightedArea = UIView(),和contentView.addSubView(specialHighlightedArea),然后布局它或添加约束以使用自动布局;
3.如果你不需要高亮效果,只需要编写一个名为'shouldHighlightItemAtIndexPath'的方法定义UICollectionViewDelegate并使其返回false,或者从superView中设置cell.shouldTintBackgroundWhenSelected = false和设置specialHighlightedArea = nil并删除它。

/// same with UITableViewCell's selected backgroundColor
private let highlightedColor = UIColor(rgb: 0xD8D8D8) 

/// you can make all your collectionViewCell inherit BaseCollectionViewCell
class BaseCollectionViewCell: UICollectionViewCell {

    /// change it as you wish when or after initializing
    var shouldTintBackgroundWhenSelected = true

    /// you can give a special view when selected
    var specialHighlightedArea: UIView? 

    // make lightgray background display immediately(使灰背景立即出现)
    override var isHighlighted: Bool { 
        willSet {
            onSelected(newValue)
        }
    }

    // keep lightGray background until unselected (保留灰背景)
    override var isSelected: Bool { 
        willSet {
            onSelected(newValue)
        }
    }

    func onSelected(_ newValue: Bool) {
        guard selectedBackgroundView == nil else { return }
        if shouldTintBackgroundWhenSelected {
            contentView.backgroundColor = newValue ? highlightedColor : UIColor.clear
        }
        if let area = specialHighlightedArea {
            area.backgroundColor = newValue ? UIColor.black.withAlphaComponent(0.4) : UIColor.clear
        }
    }
}

extension UIColor {
    convenience init(rgb: Int, alpha: CGFloat = 1.0) {
        self.init(red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgb & 0xFF00) >> 8) / 255.0, blue: CGFloat(rgb & 0xFF) / 255.0, alpha: alpha)
    }
}

回答by Brian

Simple binary logic solution. Works with Swift 3 and 4:

简单的二进制逻辑解决方案。适用于 Swift 3 和 4:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt
    indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as! CategoryCell
    let lastCellColor = cell.backgroundColor
    if cell.isSelected {cell.backgroundColor = .green} else {cell.backgroundColor = lastCellColor}
}

回答by Mihai Georgescu

Add all the subviews inside contentView, use backgroundViewand selectedBackgroundViewfrom UICollectionViewCell. Do not set contentView.backgroundColor.

添加里面的所有子视图contentView,使用backgroundViewselectedBackgroundView来自UICollectionViewCell。不要设置contentView.backgroundColor

// Add this inside your cell configuration.
private func setupSelectionColor() {
    let backgroundView = UIView()
    backgroundView.backgroundColor = .white
    self.backgroundView = backgroundView

    let selectedBackgroundView = UIView()
    selectedBackgroundView.backgroundColor = .orange
    self.selectedBackgroundView = selectedBackgroundView
}

// Add the deselection inside didSelectCallback
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    collectionView.deselectItem(at: indexPath, animated: true)
}