2013年5月19日日曜日

Android Viewのカスタム属性の作り方

自作のViewにカスタム属性を定義してレイアウトXMLから設定を変えられるようにする場合は、attr.xmlのdeclare-styleableで定義をする方法についてのメモ。

背景色の属性

背景色関連の属性は以下のように色(color)や画像(drawable)で設定できるようにできるとよい。
<!-- 色(color)でmyBackgroundを指定する -->
<myapp.MyView
  android:id="@+id/myview"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  myapp:myBackground="#ffff0000"
/>

<!-- イメージ(drawable)でmyBackgroundを指定する -->
<myapp.MyView
  android:id="@+id/myview"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  myapp:myBackground="@drawable/bg"
/>

こんなときはまず attr.xmlでは以下のようにreferencecolorの属性として定義する。

<resources>
  <declare-styleable name="MyView">
    <attr name="myBackground" format="reference|color"/>
  </declare-styleable>
</resources>

自作ViewのJava側ではDrawableとして受け取り、背景色を設定したいviewにsetBackgrund()で設定する。 colorもDrawableで受けることができ、背景色として設定できるようだ。 この方法でよいのか公式なドキュメントを確認できていないが問題なく動いているようである。

public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);

  Drawable myBackground = a.getDrawable(R.styleable.MyView_myBackground);
  if (myBackground != null) {
    myView.setBackgroundDrawable(myBackground);
  }
}
ちなみに、AttributeSet.getColor()で受けると以下のようなエラーが出る。 背景色を設定できるようにする場合は特に理由がなければDrawableで受けるようにしておいたほうが無難だろう。

Caused by: android.view.InflateException: Binary XML file line #35: Error inflating class myapp.MyView
    at android.view.LayoutInflater.createView(LayoutInflater.java:613)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:270)
    at android.app.Activity.setContentView(Activity.java:1881)
    at myapp.MyActivity.onCreate(MyActivity.java:58)
    at android.app.Activity.performCreate(Activity.java:5104)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
    ... 11 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
    at android.view.LayoutInflater.createView(LayoutInflater.java:587)
    ... 24 more
Caused by: android.content.res.Resources$NotFoundException: File res/drawable-hdpi/bg.png from drawable
resource ID #0x7f020011: .xml extension required
    at android.content.res.Resources.loadColorStateList(Resources.java:2094)
    at android.content.res.TypedArray.getColor(TypedArray.java:319)
    at myapp.SampleQueryView.(SampleQueryView.java:54)
    ... 27 more

0 件のコメント:

コメントを投稿