web-dev-qa-db-ja.com

UICollectionViewの選択と選択解除の問題

そのため、多くの画像が関連付けられたメインオブジェクトがあります。画像もオブジェクトです。

コレクションビューコントローラーがあり、そのコントローラーには

cellForItemAtIndexPath

メインオブジェクトに基づいて、現在の画像が関連付けられている場合、選択済みをtrueに設定します。しかし、ユーザーがメインオブジェクトとの関連付けを削除するために、現在のセルをいつでも「選択解除」できるようにしたいと思います。

「selected to true」に設定すると、cellForItemAtIndexPathのメインオブジェクトと画像の間に関係がある場合、選択解除はオプションではなくなります。

didDeselectItemAtIndexPath

そして

didSelectItemAtIndexPath

ログでテストして、呼び出されるかどうかを確認します。セルが選択済みに設定されている場合-ネザーが呼び出されますが、cellForItemAtIndexPathでセルを選択済みに設定しない場合は、必要なすべてを選択および選択解除できます。

これは、コレクションビューが機能することを意図した方法ですか?私はドキュメントを読みましたが、このことについては話していないようです。ドキュメントを解釈して、Table View Cellと同じように機能することを意味します。いくつかの明らかな変更あり

これは、コントローラーが正しくセットアップされ、適切なデリゲートメソッドを使用していることも示しています。

45
bworby

私は同じ問題を抱えていた、すなわち。設定cell.selected = YES in [UICollectionView collectionView:cellForItemAtIndexPath:]その後、セルをタップしても選択を解除できません。

今の解決策:both[UICollectionViewCell setSelected:]および[UICollectionView selectItemAtIndexPath:animated:scrollPosition:] in [UICollectionView collectionView:cellForItemAtIndexPath:]

85
user2405793

CellクラスにカスタムsetSelectedメソッドがありますか? [super setSelected:selected]そのメソッドで?

複数の選択を使用していて、選択したセルを選択解除できないという謎の問題がありました。スーパーメソッドを呼び出すと、問題が修正されました。

46
Aneel

UICollectionViewの選択解除の問題があり、collectionViewで複数選択を許可していないことがわかりました。そのため、テスト中は常に同じセルで試してみましたが、単一選択がオンの場合、すでに選択されているセルの選択を解除することはできません。

追加する必要がありました:

myCollectionView.allowsMultipleSelection = YES;
45
Fjohn

これはちょっと古いですが、Swiftを使用して同じ問題に遭遇したため、答えを追加します。

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

セルはまったく選択されませんでした。しかし、使用する場合:

cell.selected = true

選択されましたが、セルを選択/選択解除できなくなりました。

私の解決策(両方の方法を使用):

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

この2つのメソッドが呼び出されるとき:

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

完璧に機能しました!

34
dmlebron

UICollectionViewUITableViewControllerと比べてこんなに乱雑な理由はわかりません。

_setSelected:_が複数回呼び出される理由は、シーケンスメソッドが呼び出されるためです。シーケンスは、UITextFieldDelegateメソッドのシーケンスと非常に似ています。

collectionViewが実際にセルを選択する前にメソッド_collectionView:shouldSelectItemAtIndexPath:_が呼び出されるのは、実際に「選択されるべきだ」と尋ねているからです。

_collectionView:didSelectItemAtIndexPath:_は、実際にcollectionViewがセルを選択した後に呼び出されます。したがって、名前は「did select」でした。

これがあなたのケースで起こっていることです(そして私のケース、そして私はこれについて何時間も取り組まなければなりませんでした)。

選択したセルは、選択を解除するためにユーザーによって再度タッチされます。 _shouldSelectItemAtIndexPath:_は、セルを選択する必要があるかどうかを確認するために呼び出されます。 collectionViewはセルを選択し、didSelectItemAtIndexPathが呼び出されます。この時点で行うことは、セルのselectedプロパティがYESに設定された後です。そのため、_cell.selected = !cell.selected_のようなものは機能しません。

TL; DR-_collectionView:shouldSelectItemAtIndexPath:_を呼び出して、デリゲートメソッド_deselectItemAtIndexPath:animated:_でcollectionViewのセルの選択を解除し、NOを返します。

私がしたことの短い例:

_- (BOOL)collectionView:(OPTXListView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *selectedItemIndexPaths = [collectionView indexPathsForSelectedItems];

    if ([selectedItemIndexPaths count]) {
        NSIndexPath *selectedIndexPath = selectedItemIndexPaths[0];

        if ([selectedIndexPath isEqual:indexPath]) {
            [collectionView deselectItemAtIndexPath:indexPath animated:YES];

            return NO;
        } else {
            [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

            return YES;
        }
    } else {
        [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

        return YES;
    }
}
_
10
funct7

Swift 2.0。

ViewDidLoad()で以下を設定することができました

collectionView.allowsMultipleSelection = true;

その後、これらのメソッドを実装しました

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

最後に

class MyCell : UICollectionViewCell {

    ....

    func toggleSelected ()
    {
        if (selected){
            backgroundColor = UIColor.orangeColor()
        }else {
            backgroundColor = UIColor.whiteColor()
        }
    }

}
7
Trent
 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
    }

}

私が見つけたシンプルなソリューション

2
Davin

IOS 9の時代に生きるには、ここで確認すべきことがいくつかあります。

  1. _collectionView.allowsSelection_がYESに設定されているか確認してください
  2. _collectionView.allowsMultipleSelection_がYESに設定されているかどうかを確認します(その機能が必要な場合)

今度はファンの部分が来ます。 Appleを聞いて、backgroundColor自体ではなく_cell.contentView_にcellを設定すると、そのselectedBackgroundViewを非表示にしたことになります。目に見える。

_(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
_

SelectedBackgroundView(_cell.selected_および_selectItemAtIndexPath..._でオン/オフされるもの)を使用する場合は、次のようにします。

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

そしてそれはうまく動作するはずです。

2

問題を理解していることはわかりませんが、選択したステータスはセルごとに設定され、セル内のすべてのサブビューが含まれます。 「メインオブジェクトには多くの画像が関連付けられています」という意味を説明しません。サブビューのように関連付けられていますか?または、どのような関連付けを正確に意味しますか?

設計上の問題のように思えます。おそらく、必要な関連オブジェクトをすべて含むUIViewサブクラスが必要です。その後、そのサブクラスをコンテンツビューとして設定できます。たとえば、画像に関連する画像、説明、録音がある場合にこれを行います。すべてがサブクラスで定義され、これらの各サブクラスが単一のセルのコンテンツビューになります。

また、画像を含むフォルダーに関連する画像を配置しました。この設定では、フォルダーと画像にはそれぞれサブクラスがあり、いずれかがコンテンツビューとしてセルに添付されます(これらは単一のエンティティとしてコアデータに格納されます)。

おそらくあなたはあなたの問題をさらに説明できますか?

1

私はカスタムセルサブクラスを使用しています。私にとっては、サブクラスのprepareForReuse()self.selected = falseを設定するだけでした。

1
Chris

見たことがありますか:

- (BOOL)collectionView:(PSTCollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;

あなたの問題をより明確に述べてください、そしておそらく私たちはそれの一番下に到達することができます。 UICollectionViewで時間を過ごしました。

問題は、cell.selected = YESプログラムで、理由didSelectItemAtIndexPath:が呼び出されないのは、collectionView自体がセルの選択を担当する場合にのみ使用されるためです(タップ経由など)。

1
cleverbit

この質問は6歳ですが、私は気にしません。ここに着いて、答えがどれも私の特定の問題を解決しないことを発見した後、私は最終的にこの質問に対する最良の答えであると考えるものに思いつきました。そこで、後世のためにここに投稿しています。

CellForItemAtIndexPathでセルを選択することは、UICollectionViewがそのメソッドを呼び出す方法のために問題があります。コレクションビューを最初に設定するときに呼び出されるだけではありません。これは、コレクションビューがスクロールされるときに継続的に呼び出されます。これは、コレクションビューがデータソースに対して表示可能なセルのみを要求するため、オーバーヘッドが大幅に節約されるためです。

コレクションビューはすべてのセルをメモリに保持するわけではないため、独自のセルの選択状態を管理する必要があります。 isSelectedプロパティが設定されているセルを提供することを期待していません。彼らはあなたにセルを提供することを期待し、適切であればそれらに選択されたプロパティを設定します。

AppleはUICollectionViewCellのisSelectedプロパティを直接設定しないように警告します。UICollectionViewはあなたのためにそれを処理することを期待しています。

[〜#〜] so [〜#〜]、答えは[〜#〜] not [〜#〜] cellForItemAtIndexPathメソッドでセルの選択を試みます。最初に選択するセルを選択する最適な場所は、UICollectionViewControllerのviewWillAppearメソッドです。そのメソッドでは、UICollectionView.selectItem(at:animated:scrollPosition :)を呼び出して、目的のセルをすべて選択し、セルで直接DO N'T set isSelectedを設定します。

1
Ryan Ballantyne

both _[UICollectionViewCell setSelected:]_および_[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]_の_[UICollectionView collectionView:cellForItemAtIndexPath:]_を呼び出しても機能しない場合は、dispatch_async(dispatch_get_main_queue(), ^{});ブロック内で呼び出してみてください。

それが最終的に私のためにそれを修正したものです。

0
Fran Sevillano