2017/04/27

DataBindingでViewのtagにenumを設定する

DataBindingを使えばViewのtagフィールドに好きなオブジェクトを差し込めるので↓のような実装を試してみました.
固定長リストをlayout.xmlで定義する際にenumを設定すれば, onClickリスナーでそれを取り出して使うことができます.

キャストする箇所がアレですが,,

<layout>
<data>
 <import type="hoge.foo.Type"/>
</data>

<LinearLayout
  ...
  >
    <TextView
      ...
      android:tag="@{Type.A}" />

    <TextView
      ...
      android:tag="@{Type.B}" />

    <TextView
      ...
      android:tag="@{Type.C}" />

    <TextView
      ...
      android:tag="@{Type.D}" />
</LinearLayout>
</layou>
@Override public void onClick(View v) {
  Object tag = v.getTag();
  if (tag == null || !(tag instanceof Type)) return;

  Type type = Type.class.cast(tag);
  ...
}

以上です.

2017/04/25

レイアウトのサイズ指定で足し算する

Viewのサイズを指定する時に, (A)のサイズと(B)のサイズの和を指定したい場合があります.
AとB, どちらもアプリで定義しているサイズであれば, その和を新たなdimensとして定義することもできますが,
例えば “アクションバーの高さ + 8dp” など, 片方がアプリの管理下にない場合はdimensで定義することができなくなります.
コード上で指定することもできますが, レイアウトの問題はレイアウトXMLで完結させたいところ.
理想としては下記のような指定ができれば良いのですが, Androidではこれができません.

<View
  android:paddingTop="?attr/actionBarSize + 8dp" />

そこで, DataBindingの”式”を使えばそれっぽく書くことができます.

<layout>
 <data>
  <import type="hoge.foo.Dimens"/>
  <import type="hoge.foo.Dimens.ActionBar"/>
 </data>

 <View
   android:paddingTop="@{ActionBar.height(context) + Dimens.dpToPx(context, 8)}"
public final class Dimens {
  @Px public static int dpToPx(Context c, int dp) {
    DisplayMetrics metrics = c.getResources().getDisplayMetrics();
    return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics) + 0.5f);
  }

  public static class  ActionBar  {
    @Px public static int height(Context c) {
      TypedValue tv = new TypedValue();
      if (c.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
        return TypedValue.complexToDimensionPixelSize(tv.data,
            c.getResources().getDisplayMetrics());
      }
      return 0;
    }
  }

以上です.