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; } }
ListViewのアイテム
ListViewのアイテムに対して、onClickListenerなどを設定すると、OnItemClickListenerが呼ばれない。
推測だが、以下のようなものなのだろう。
View階層 | 押下通知 | 説明 |
---|---|---|
View | ↓ | ユーザの押下通知はスルー |
ListView | ↓ | ユーザ押下が処理される。ListViewは、押されている位置に対応する場所のViewに対して、performClick()する。 |
ViewでOnClickを設定している場合
View階層 | 押下通知 | 説明 |
---|---|---|
View | ↓ | このViewのOnClick()で消費されて、ListViewまで届かない。 |
ListView | 結果、OnItemClickListenerが呼ばれない |
スクロール時の描画方法
どうやっているのかずっと気になっている。
ScrollViewのソースコードを読み込む
onTouchEvent() をハンドリングしている
タッチ移動時
ACTION_MOVE -> ScrollView::scrollBy -> ScrollView::scrollTo -> View::scrollTo -> invalidate
フリング時
ACTION_UP -> ScrollView::fling -> invalidate -> ・・・-> ViewGroup::drawChild -> ScrollView::computeScroll -> Scrollerで位置計算 -> postInvalidate
SlidingTab のアニメーション
ACTION_MOVE -> SlidingTab::moveHandle
移動量の分だけmRight/mLeftを設定
閾値を超えたらアニメーション開始
Gallary
mFlngRunnableのメソッドで開始 startUsing*****メソッド
Gallary::trackMotionScroll() によって位置を再計算して、invalidate()で再描画を繰り返す
要素の追加は?
ViewAnimator
ひとつのViewを表示する。
アニメーションは、Animationクラスを利用
ViewSwitcher
二つのViewを切り替えて表示する
ImageSwitcher
Viewの中でもImageViewを切り替えて表示する
ViewFlipper
自動的にViewAnimator::showNext()呼ぶだけ。アニメーションは特に管理していない。