いまさら Raspberry Pi3+

GUI/CLIログイン切換え

http://ysdyt.github.io/blog/2015/03/27/raspi-cli-gui-login/

  • ROM焼き
  • SSHWIFI設定
  • ユーザ設定
  • raspi-config
  • ソフトウェアアップデート
  • 延命措置
    • swap無効化
    • tmp領域のRAM化

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()呼ぶだけ。アニメーションは特に管理していない。

ロック画面のリソース

ロック画面のスライドバーは、どうやって作られているのだろうか。

キーワード
com.android.internal.widget.RotarySelector
keyguard_screen_rotary_unlock.xml

com.android.internal.widget.SlidingTab
res/layout/keyguard_screen_tab_unlock.xml

internalばかりだ。リフレクションを利用する?