fresh digitable

めんどくさかったなってことを振り返ったり振り返らなかったりするための記録

SYSTEM_UI_FLAG_IMMERSIVEとSYSTEM_UI_FLAG_IMMERSIVE_STICKYとの違い

API Level 19からは全画面表示をしたいときにどっちかのフラグをセット(View.setSystemUiVisibility())することで没入感をより高めることができる。

SYSTEM_UI_FLAG_HIDE_NAVIGATIONSYSTEM_UI_FLAG_FULLSCREENとを合わせてセットすることで、システムUIが画面外に押し出されている状態になる。外にあるUIを引っ張り出すように(上か下エッジからスワイプ)すると表示される。二つのフラグの違いは次の通り。

  • SYSTEM_UI_FLAG_IMMERSIVE: システムUIが引っ張り出されたら、システムUIが消えた状態に戻らない
  • SYSTEM_UI_FLAG_IMMERSIVE_STICKY: システムUIが引っ張り出されたあと、しばらくするとまたシステムUIが引っ込む

IMMERSIVEの方を使い、View#setOnSystemUiVisibilityChangeListener()にリスナをセットすることでシステムUIの見え方が変わったイベントを受け取れる。このリスナの中で独自のUIを表示させるようにして、時間とか特定の操作で再びimmersiveな状態に遷移させれば良い。

システムUIが無いレイアウトに設定するためのフラグも一緒にセットしてやればカクついたりしない。詳しくは公式リファレンスを。

developer.android.com

カスタムビューに独自のスタイル属性を定義する

メディアのサムネイルを同じ大きさで横一列に並べるコンテナクラスを作ったので、中にいれるサムネイルの数をレイアウトリソースで定義できるようにした。

res/values/attr.xmldeclare-styleableを追加する

<resources>
    <declare-styleable name="MyCustomView">
        <attr name="thumbCount" format="integer" />
    </declare-styleable>
</resources>

layoutリソースファイルで次のように使う

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >
    <com.freshdigitable.MyCustomView
        android:id="@+id/custom_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:thumbCount="4"
        />
</LinearLayout>

独自のネームスペースを定義しようとしたら、「gradleプロジェクトではapp:.../res-autoを使え」的なことを言われた気がする。

カスタムビューのコンストラクタで設定した値を受け取る

(色々と省略している)

public class MyCustomView extends View {
  private final int thumbCount;

  public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
    try {
      this.thumbCount = a.getInt(R.styleable.MyCustomView_thumbCount, 0);
    } finally {
      a.recycle();
    }
  }
}

TextViewをextendsする

Viewを継承して自分のカスタムビューを作ろうとする時、3種類のコンストラクタをオーバーライドしなければならない。今までは何も考えずに

public HogeView(Context context) {
  this(context, null);
}

public HogeView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
}

public HogeView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
}

などとしていたが、TextViewなどのandroid.R.attr.xxxStyleがあるものについては、引数が2このコンストラクタの中を

public MyCustomTextView(Context context, AttributeSet attrs) {
  this(context, attrs, android.R.attr.textViewStyle);
}

のようにしなければならない。

TextViewはsupport-libの中にAppCompatTextViewがあるのでこれを継承する。というか、他のTextViewと同じ色にならなくてなんでだろうな〜スタイルとかいじってないつもりなのにな〜とAppCompatTextViewのソースを読んでいたところこの事実に気づいた。引数3つのやつでsuperを呼ぶより、それぞれのコンストラクタの中でsuperを呼んで、さらにinit(Context, AttributeSet, int)みたいな初期化メソッドを用意して呼んでやるのがこれからは良いのだろうか。