Android OS4.1 4.2でCheckedTextViewのisCheckedメソッドの初期値が変わった? ときの代替方法

Android で ListView と CheckedTextView を使うことで、複数行のリストチェックボックスをつくることができます。

// xmlからListViewを取得
ListView listView = (ListView) findViewById(R.id.list);

_arrayAdapter = new testArrayAdapter ... // ArrayAdapterクラスを継承したアダプタークラス

listView.setAdapter(_arrayAdapter);
listView.setItemsCanFocus(false);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setOnItemClickListener( new CheckedItemOnclick() );

複数行を選択するために ListView.setChoiceMode()メソッド に ListView.CHOICE_MODE_MULTIPLE をセットしています。
選択した行のイベントリスナーとして ListView.setOnItemClickListener()メソッド に OnItemClickListenerインターフェース を実装したクラスをセットしています。

private class CheckedItemOnclick implements OnItemClickListener {
    @Override
    public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
        final CheckedTextView checkedTextView = (CheckedTextView) view;

        boolean isChecked = checkedTextView.isChecked();

}

ここで、今回の問題である ListView.isChecked()メソッド の初期値が、Android 0S 4.0以下と4.1以上で変わっていると思われます。


デバックモードで値を確認したところ
Android OS 2.2 => ListView.isChecked() = false
Android OS 2.3 => ListView.isChecked() = false
Android OS 4.0 => ListView.isChecked() = false
Android OS 4.1 => ListView.isChecked() = true
Android OS 4.2 => ListView.isChecked() = true


となっており、なんとか解決できないかと次の2つを試してみました。

1.LayoutInflaterでxmlをインフレートする前に ListView.isChecked() に false を指定する

public class testArrayAdapter<T> extends ArrayAdapter<T> {
    /** 
      :
    **/
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CheckedTextView view = (CheckedTextView) convertView;
        if (convertView == null) {
            view = _layoutInflater.inflate(_rowResouceId, null);
        }
        view.setChecked( false );
        return view;
    }
}

この方法でも、結果は同じでダメでした。


2.上記でインフレートするxmlにある CheckedTextView のxml属性にある android:checked に false を指定する

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    android:gravity="left"
    android:checked="false" />

この方法でも、結果は同じでダメでした。


どうしても CheckedTextView の値を直せないので、 ListView の行ごとに isSelected変数 を持たせるようする方法しか考えつきませんでした...orz
さて、どうしたものか。


===== 2012/12/20 18:58 追記 =====

[twitter:@mryo0826]さんに、対応方法を教えていただきました!

内容は、こちら

つまり、ListView.getCheckedItemPositions()メソッドからリストのboolean配列( SparseBooleanArray )を取得し、対応するポジションのチェック判定を取得する方法です。

private class CheckedItemOnclick implements OnItemClickListener {
    @Override
    public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {

        final SparseBooleanArray checkedList = _listView.getCheckedItemPositions();
        boolean isChecked = ! checkedList.valueAt(position);

}

ここで注意点が1つ、それぞれのOSごとの checkedList.valueAt(position) の出力結果は...

Android OSisChecked()checkedList.valueAt(position)
2.2falsetrue
2.3falsetrue
4.0falsetrue
4.1truetrue
4.2truetrue
すべて true になっています

なので、Android 4.0以下で行っていた判定をそのまま使いたい場合は、 ! (否定) を忘れずに。

http://www.st-hatena.com/users/sa/samril/user_p.gif@mryo0826さん、大変助かりました(_ _)