AlertDialog setMultiChoiceItems、バグまたは非自明な機能

こんにちは、Habr!



エントリー



過去2か月間、Androidの1つのプロジェクトに取り組んできました。 しかし、今は彼についてではありません。私は彼について書いてみますが、すべてに時間があります



プロジェクトに取り組んでいる間ずっと、多くの興味深いことが起こりました(そして起こりました)。 今日は少し話をしたいです。



物語の始まり



ある夕方、正月休みの直前に、オフィスで働き、お気に入りのカモメを飲みながら、プロジェクトの機能の次の部分を書きました。



リストから要素を複数選択できる可能性のある通常のダイアログを作成する必要がありました。すべての要素をすぐにマーク/チェック解除し、選択した要素を保存して、ダイアログが表示されたらすぐに選択できます。

すぐに言ってやった。



実際にはコード自体:

protected ArrayList<String> items; protected ArrayList<String> selectedItems; protected void showMyDialog() { int count = items.size(); boolean[] checkedItems = new boolean[count]; for (int i = 0; i < count; i++) checkedItems[i] = selectedItems.contains(items.get(i)); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMultiChoiceItems(items.toArray(new String[items.size()]), checkedItems, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { ListView list = ((AlertDialog) dialog).getListView(); if (isChecked) { if (which == 0) { for (int i = 0; i < list.getCount(); ++i) list.setItemChecked(i, true); selectedItems.clear(); selectedItems.addAll(items); } else selectedItems.add(items.get(which)); } else { if (which == 0) { for (int i = 0; i < list.getCount(); ++i) list.setItemChecked(i, false); selectedItems.clear(); } else selectedItems.remove(items.get(which)); } } }); AlertDialog dialog = builder.create(); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.show(); }
      
      







問題は解決されたように見えるので、テストしてリラックスするために明確な良心をもって進むことができます(まあ、WOT =をプレイ)。



ボタンマーク\動作したすべての要素のチェックを外します。 しかし、最初にいくつかの要素を選択し、ボタンを使用してすべての要素をマークし、すぐにすべてのチェックを解除すると、自分がマークした要素のペアはチェックされたままになります。

少し実験して、私はそれが休みに行き、朝に物事を整理し続ける時だと決めました。 去る前に、私はstackoverflowでこの質問を提起しました。



午前中に仕事に着き、彼のトピックを見て、実際的なアドバイスを見ていなかったので、彼はさらに分析を続けました。

何が起こっているかを簡単に分析した結果、問題が再現されるのは、関数が

setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener)





checkedItems配列を渡します。代わりにnullが渡された場合、問題は発生しませんでした。

stackoverflowについて再び質問を提起しましたが、残念ながら誰も何もアドバイスしませんでした。



すでに12月29日であり、プロジェクトにはまだ多くのタスクがありました。そのため、配列を送信せずにコードを少し書き直した後、問題は解決しました。

Googleのバグトラッカーに問題を報告し、さらに作業を続けると、この話を忘れてしまいました。



私たちの日々



今日、メールを見て、誰かが私のバグレポートに応答しているのを見ました。 表示後、さらに2、3人が同じ問題に直面していることが明らかになりました。



少しビジネスを整理したので、私は問題をもう一度見ることにしました。

アイデアが思い浮かびましたが、すでに来ているように思えたので、確認しましたが、もう一度確認しました。

その目的は、checkedItems配列をクラスのフィールドにし、リスナーでもそれを使用することでした。

その結果、onClickメソッドは次の形式を取りました。



 public void onClick(DialogInterface dialog, int which, boolean isChecked) { ListView list = ((AlertDialog) dialog).getListView(); if (isChecked) { if (which == 0) { for (int i = 0; i < list.getCount(); ++i) { list.setItemChecked(i, true); checkedItems[i]=true; } selectedItems.clear(); selectedItems.addAll(items); } else selectedItems.add(items.get(which)); } else { if (which == 0) { for (int i = 0; i < list.getCount(); ++i) { list.setItemChecked(i, false); checkedItems[i]=false; } selectedItems.clear(); } else selectedItems.remove(items.get(which)); } }
      
      







それでも、はい、これは元の問題を解決しました。



結果。



私はそれが好きではありませんが、私たちは結論づけることができます:

checkedItems配列で要素の状態が未チェック(false)として示されている場合、チェックすると画面上でマークされます(ただし、配列ではマークされません)。チェックを外すと、マークは削除されます。

ただし、checkedItems配列で要素の状態がマークされている(true)と示されている場合、チェックを外しても、要素は画面上でチェックされたままです。 配列内でマークされたままになります。



それが起こった話です。おもしろくて、あなたが時間を無駄にしないで、でも私と同じように。

ご関心をお寄せいただきありがとうございます。ご質問がありましたら、お気軽にお答えします。

次の記事では、プロジェクト自体についてお話したいと思いますが、それは興味深いはずです。



All Articles