ListView の CHOICE_MODE_SINGLE

ListViewのシングルチョイスモードは、リストアイテムは、Checkableなクラスでないと、
シングルチョイスすることができない。

Checkableなクラスは、CheckBox, CheckedTextView, CompoundButton, RadioButton, ToggleButton ぐらいなので、
CHOICE_MODE_SINGLEでは、自由なレイアウトが難しい。

したがって、CheckalbeなLinearLayoutを作ってみる。
ポイントは、2点。

  • setCheckedメソッドでは、refreshDrawableState()をコールする。
            if (mChecked != checked) {
                 mChecked = checked;
                 refreshDrawableState();
             }
  • onCreateDrawableState()をオーバーライドして、android.R.attr.state_checkedを追加(マージ)するようにする。
        if (isChecked()) {
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        }

全容は以下のとおり。

package com.misetu.test.listview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class CheckableLinearLayout extends LinearLayout implements Checkable {

	private static final String TAG = "CheckableLinearLayout";
    private static final int[] CHECKED_STATE_SET = {
        android.R.attr.state_checked
    };
	boolean mChecked;
	
	public CheckableLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public boolean isChecked() {
		Log.d(TAG, "isChecked():"+this);
		return mChecked;
	}

	@Override
	public void setChecked(boolean checked) {
		Log.d(TAG, "setChecked("+checked+"):" + this);
            if (mChecked != checked) {
                 mChecked = checked;
                 refreshDrawableState();
             }
	}

	@Override
	public void toggle() {
		Log.d(TAG, "toggle()" + this);
		mChecked = !mChecked;

	}

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        }
        return drawableState;
    }
}