UICollectionView Select and Deselect issue

2019-01-13 00:38发布

So I have a main object that has many images associated with it. An Image is also an object.

Say you have a collection view controller, and in that controller you have

cellForItemAtIndexPath

well based on the main object, if it has the current image associated with it I want to set selected to true. But I want the user to be able to "un-select" that current cell at any time to remove its association with the main object.

I find that if you set "selected to true" - if there is an relation between the main object and image in cellForItemAtIndexPath, de-selection is no longer an option.

in

didDeselectItemAtIndexPath

and

didSelectItemAtIndexPath

I test with a log to see if they are called. If a cell is set to selected - nether gets called, but If I never set a cell to selected in cellForItemAtIndexPath I can select and deselect all I want.

Is this the intended way a collection view is supposed to work? I read the docs and it does not seem to talk about this being so. I interpret the docs to mean it works the way a table view cell would. with a few obvious changes

This also shows the controller is set up correct and is using the appropriate delegate methods.... hmmmm

13条回答
三岁会撩人
2楼-- · 2019-01-13 01:10

Do you have a custom setSelected method in your Cell class? Are you calling [super setSelected:selected] in that method?

I had a mysterious problem where, I was using multiple selection, I could not deselect cells once they were selected. Calling the super method fixed the problem.

查看更多
Summer. ? 凉城
3楼-- · 2019-01-13 01:13

I had the same issue, ie. setting cell.selected = YES in [UICollectionView collectionView:cellForItemAtIndexPath:] then not being able to deselect the cell by tapping on it.

Solution for now: I call both [UICollectionViewCell setSelected:] and [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] in [UICollectionView collectionView:cellForItemAtIndexPath:].

查看更多
Root(大扎)
4楼-- · 2019-01-13 01:14

This is kind of old but, since I encounter the same issue using swift I will add my answer. When using:

 collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: [])

The cell didn't get selected at all. But when using:

cell.selected = true

It did get selected but I wasn't able to select/deselect the cell anymore.

My solution (use both methods):

cell.selected = true
collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: .None)

When this two methods are called in:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell

It worked perfectly!

查看更多
女痞
5楼-- · 2019-01-13 01:17
 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    if cell?.selected == true{
        cell?.layer.borderWidth = 4.0
         cell?.layer.borderColor = UIColor.greenColor().CGColor
    }   
}func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    if cell?.selected == false{
            cell?.layer.borderColor = UIColor.clearColor().CGColor
    }

}

Simple Solution i found

查看更多
叼着烟拽天下
6楼-- · 2019-01-13 01:20

Living in the age of iOS 9, there are multiple things to check here.

  1. Check do you have collectionView.allowsSelection set to YES
  2. Check do you have collectionView.allowsMultipleSelection set to YES (if you need that ability)

Now comes the fan part. If you listen to Apple and set backgroundColor on the cell.contentView instead of cell itself, then you have just hidden its selectedBackgroundView from ever being visible. Because:

(lldb) po cell.selectedBackgroundView
<UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>>

(lldb) po cell.contentView
<UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>>

(lldb) pviews cell
<MyCell: 0x7fd2dae1aa70; baseClass = UICollectionViewCell; frame = (0 0; 64 49.5); clipsToBounds = YES; hidden = YES; opaque = NO; layer = <CALayer: 0x7fd2dae1ac80>>
   | <UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>>
   | <UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>>
   |    | <UIView: 0x7fd2dae24a60; frame = (0 0; 64 49.5); clipsToBounds = YES; alpha = 0; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7fd2dae1acc0>>
   |    | <UILabel: 0x7fd2dae24bd0; frame = (0 0; 64 17.5); text = '1'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae240c0>>
   |    | <UILabel: 0x7fd2dae25030; frame = (0 21.5; 64 24); text = '1,04'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae25240>>

(lldb) po cell.contentView.backgroundColor
UIDeviceRGBColorSpace 0.4 0.4 0.4 1

So if you want to use selectedBackgroundView (which is the one being turned on/off with cell.selected and selectItemAtIndexPath...) then do this:

cell.backgroundColor = SOME_COLOR;
cell.contentView.backgroundColor = [UIColor clearColor];

and it should work just fine.

查看更多
闹够了就滚
7楼-- · 2019-01-13 01:21

Cell selection and deselection is best handled by setting a backgroundView and a selected background view. I recommend making sure that both of these views' frames are set correctly in the layoutSubviews method (if you set the selected and background view via IB).

Don't forget to set your contentView's (if you have one) background color to clear so the correct background view shows through.

Never set the cell's selection directly (i.e. via cell.selected = YES), use the methods designed for this purpose in the collection view. It is clearly explained in the documents, although I will agree the information is somewhat fragmented across guides.

You should not need to poke into a cell's background colors directly in your collectionView datasource.

Also, as a final note, don't forget to call [super prepareForReuse] and [super setSelected:selected] if you are implementing these in your cell's class, as you might be preventing the cell's superclass from doing the cell selection.

Hit me up if you need further clarification on this subject.

查看更多
登录 后发表回答