2013/03/18
onListItemClick() の中で isChecked() を呼んではいけない?
少し前に、知人に頼まれて作った Androidアプリの動作がおかしいとのこと。どうも、Galaxy Nexus を 4.0.2 → 4.1.1 にアップデートしてからおかしくなったらしい。
調べてみると、ListActivity.onListItemClick() の中で CheckedTextView.isChecked() を呼んだ時の挙動が変化した模様。
public class MainActivity extends ListActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] listItems = { "1", "2", "3" };
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
ListAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, listItems);
setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// ↓ 少なくとも Android 4.2 までは空関数
// super.onListItemClick(l, v, position, id);
CheckedTextView cv = (CheckedTextView) v;
Log.d(TAG, "isChecked " + cv.isChecked());
}
}
これを、Android 4.0.4 のエミュレータで動作させると以下の通り
// OFF → ON isChecked false // ON → OFF isChecked true
Android 4.2 のエミュレータで動作させると以下の通り
// OFF → ON isChecked true // ON → OFF isChecked false
完全に動作が逆転しています…
そもそも、以前は「チェックしたのに isChecked が false」という直感に反した仕様だったので、正しい動作をするようになったと言えるのかもしれません。
ただ、この変更がどのような意図で行われたのかが不明です。
Android Developersはチェックしたのですが、それらしい記述を見つけることはできませんでした。
バグフィックスなのか、たまたま挙動が変わってしまったのか…
もし、詳しい方がいらっしゃいましたら、コメントやTwitterで是非教えてください。
とりあえずは、以下のように Android のバージョンをチェックして乗り切ることは可能かもしれません。
CheckedTextView cv = (CheckedTextView) v;
boolean isChecked = (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) ?
!cv.isChecked() : cv.isChecked();
ただし、仕様が明確に提示されていない以上、今後もまた変更が入る可能性はあります。
つまり、
onListItemClick() の中では isChecked() を呼ばない方が無難だという事になります。しかし、チェックされた瞬間に動作させたいことってありますよねぇ…
続き: OnItemClickListener.onItemClick() の中で isChecked() を呼んではいけない?
0 件のコメント:
コメントを投稿