web-dev-qa-db-ja.com

UICollectionView shouldSelectItemAtIndexPath = NOは古い選択の選択解除を避けませんか?

CollectionViewに複数のアイテムがありますが、選択できるのはそのうちのいくつかだけです。私はこれをデリゲートメソッドで処理しています:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath

私の問題は、選択可能なアイテムが選択され、次のステップで、shouldSelectItemAtIndexPathがNOを返すことによって選択できないアイテムの選択が拒否された場合に発生し、選択されたアイテムの選択が解除されます。

私も使用しようとしました

- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath

しかし、それは同じ問題です。

これは、UICollectionViewの正しい望ましい動作ですか?はいの場合、選択できない項目が選択された場合、最後に選択した項目の選択解除を回避するにはどうすればよいですか?

29
sust86

私は私の仮定を修正する必要があります:最後の選択は選択解除されません!

選択時にセルの外観を変更するために、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
13
sust86

私はこれと同じ問題を抱えていました。私はさまざまな解決策を試しましたが、私の場合、最初に機能したのは、選択したセルをリロードしてから再選択することでした。これは、コレクションビュー全体をリロードした場合でも、選択されていない外観でスタックしていたセルだけをリロードした場合でも機能しました。

私にとってうまくいかなかったアプローチ:

  • セルのselectedプロパティをtrueに設定するか、falseに切り替えてからtrueに切り替えます。
  • -selectItemAtIndexPath:animated:scrollPosition:でアイテムを選択するか、-deselectItemAtIndexPath:でアイテムの選択を解除してからもう一度選択します。
  • 選択した行のみを-reloadItemsAtIndexPaths:で再読み込みする
  • -reloadDataを使用してすべてを再読み込みします。
2

self.collectionView.allowsMultipleSelection = trueを設定してこれを解決しました。

そしてtrue-collectionView:shouldSelectItemAtIndexPath:に返したときにすべてのインデックスの選択を解除します

1
Gustavo Vergara

デリゲートメソッドDidSelectおよびDidDeselectメソッドでセルの外観を変更する必要があります。 shouldSelectメソッドでNOを返す場合、DidSelectとDidDeselectは呼び出されないため、collectionViewの選択されたステータスと一致して、外観は同じままです。

1
jx ch

6年遅れますが、他の誰かに役立つかもしれません。このような場合、そもそも特定のセルを選択できないようにする必要がある場合は、カスタムUICollectionViewCellawakeFromNib()関数にisUserInteractionEnabled = falseを追加するだけです。これはxibファイルで行うこともできますが、それほど明確ではなく、将来のメンテナには明らかでない可能性があります。

1
Orr Matarasso

UICollectionViewUITableViewControllerに比べてこんなに汚いのはなぜかわかりません...いくつかのことがわかりました。

- setSelected:が複数回呼び出されるのは、シーケンスメソッドが呼び出されるためです。シーケンスはUITextFieldDelegateメソッドのシーケンスとよく似ています。

メソッド- collectionView:shouldSelectItemAtIndexPath:は、collectionViewが実際にセルを選択する前に呼び出されます。

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

選択解除についても同様です。

TL; DR-- collectionView:shouldSelectItemAtIndexPath:を呼び出して、デリゲートメソッド- selectItemAtIndexPath:animated:scrollPosition:のセルのcollectionViewの選択を解除すると、すべて正常に動作します。

1
funct7

やってみました:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath

これは期待どおりに機能することがわかりました。

0
user2887309