CollectionViewに複数のアイテムがありますが、選択できるのはそのうちのいくつかだけです。私はこれをデリゲートメソッドで処理しています:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
私の問題は、選択可能なアイテムが選択され、次のステップで、shouldSelectItemAtIndexPathがNOを返すことによって選択できないアイテムの選択が拒否された場合に発生し、選択されたアイテムの選択が解除されます。
私も使用しようとしました
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
しかし、それは同じ問題です。
これは、UICollectionViewの正しい望ましい動作ですか?はいの場合、選択できない項目が選択された場合、最後に選択した項目の選択解除を回避するにはどうすればよいですか?
私は私の仮定を修正する必要があります:最後の選択は選択解除されません!
選択時にセルの外観を変更するために、UICollectionViewCellのsetSelectedアクセサーをオーバーライドしました。選択できない項目を選択すると、最後に選択したセルのアクセサーsetSelectedが複数回呼び出されます。まず状態NOで、次に状態YESで、最後に再びNOで。最後の状態であるNOにより、セルの外観が選択されていないセルの外観に設定されました。
この奇妙な振る舞いの理由がわかりませんし、解決できません。
私の回避策は、選択されたセルの外観をViewControllerで直接変更することです。
選択した外観を以下に設定:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
選択した外観を削除:
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
現在のセルが選択されているかどうかを確認し、意図したとおりに外観を変更します。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
私はこれと同じ問題を抱えていました。私はさまざまな解決策を試しましたが、私の場合、最初に機能したのは、選択したセルをリロードしてから再選択することでした。これは、コレクションビュー全体をリロードした場合でも、選択されていない外観でスタックしていたセルだけをリロードした場合でも機能しました。
私にとってうまくいかなかったアプローチ:
selected
プロパティをtrueに設定するか、falseに切り替えてからtrueに切り替えます。-selectItemAtIndexPath:animated:scrollPosition:
でアイテムを選択するか、-deselectItemAtIndexPath:
でアイテムの選択を解除してからもう一度選択します。-reloadItemsAtIndexPaths:
で再読み込みする-reloadData
を使用してすべてを再読み込みします。self.collectionView.allowsMultipleSelection = true
を設定してこれを解決しました。
そしてtrueを-collectionView:shouldSelectItemAtIndexPath:
に返したときにすべてのインデックスの選択を解除します
デリゲートメソッドDidSelectおよびDidDeselectメソッドでセルの外観を変更する必要があります。 shouldSelectメソッドでNOを返す場合、DidSelectとDidDeselectは呼び出されないため、collectionViewの選択されたステータスと一致して、外観は同じままです。
6年遅れますが、他の誰かに役立つかもしれません。このような場合、そもそも特定のセルを選択できないようにする必要がある場合は、カスタムUICollectionViewCell
のawakeFromNib()
関数にisUserInteractionEnabled = false
を追加するだけです。これはxibファイルで行うこともできますが、それほど明確ではなく、将来のメンテナには明らかでない可能性があります。
UICollectionView
がUITableViewController
に比べてこんなに汚いのはなぜかわかりません...いくつかのことがわかりました。
- setSelected:
が複数回呼び出されるのは、シーケンスメソッドが呼び出されるためです。シーケンスはUITextFieldDelegate
メソッドのシーケンスとよく似ています。
メソッド- collectionView:shouldSelectItemAtIndexPath:
は、collectionView
が実際にセルを選択する前に呼び出されます。
- collectionView:didSelectItemAtIndexPath:
は、実際にはcollectionView
がセルを選択した後に呼び出されます。したがって、「選択した」という名前です。
選択解除についても同様です。
TL; DR-- collectionView:shouldSelectItemAtIndexPath:
を呼び出して、デリゲートメソッド- selectItemAtIndexPath:animated:scrollPosition:
のセルのcollectionView
の選択を解除すると、すべて正常に動作します。
やってみました:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath
これは期待どおりに機能することがわかりました。