読者です 読者をやめる 読者になる 読者になる

It’s now or never

IT系の技術ブログです。気になったこと、勉強したことを備忘録的にまとめて行きます。

【Android】独自Viewを作成する

最近、Androidの勉強を始めました。

Androidは、様々な要素をxmlで定義できる点が優れていると思います。 ですが、各xmlの関連とそれらをJavaソースから参照する方法を覚えるまでは、 Javaソースを見ても???となることが多々あります。。

Androidで独自のViewを作成した場合のレイアウトファイルの定義方法や、 独自の属性の作成方法について、混乱しそうなのでメモしておきたいと思います。

独自クラスのjavaファイル定義

public class CustomView extends View {
    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

Viewのコンストラクタは以下の3つが存在します。

1.public View(Context context) 2.public View(Context context, AttributeSet attrs) 3.public View(Context context, AttributeSet attrs, int defStyle)

レイアウトパラメータを指定した場合、 上記2のattrsを持つコンストラクタが利用されます。

スタイルを指定した場合、 上記3のdefStyleを持つコンストラクタが利用されます。

レイアウトxmlでクラスを使う

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- [パッケージ名] + [クラス名]でタグを定義 -->
    <com.example.customviewsample.CustomView />

</RelativeLayout>

新しい属性の定義

標準のTextViewには、textColortextSizeなどの属性が予め用意されていますが、 独自Viewのなかで新たに属性を定義することができます。

どうやって(どこに)定義する?

属性は、res/values/attrs.xmlを作成し定義します。

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="CustomView">
   <attr name="custom_title_width" format="integer"/>
  </declare-styleable>
</resources>

<declare-styleable> name属性には、独自Viewのクラス名を定義する。

<attr> name属性には、新たに定義する属性名を定義。 format属性には、属性のフォーマット名を定義する。

formatに指定できる値には下記があります。 ・integer ・float ・boolean ・string ・color ・dimension

定義した値は、どうやって使う?

独自Viewを定義したレイアウトファイルに以下のように記載します。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:myApp="http://schemas.android.com/apk/res/com.example.customviewsample”
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- [パッケージ名] + [クラス名]でタグを定義 -->
    <com.example.customviewsample.CustomView 
        myApp:custom_title_width="123"/>

</RelativeLayout>

1.名前空間を定義する

xmlns:[名前]=“http://schemas.android.com/apk/res/[パッケージ名]“

2.属性に値をセット

myApp:custom_title_width="123"

1で定義した名前からres/values/attrs.xmlで定義した属性を参照することができます。

Javaファイルから読み込み

public class CustomView extends View {

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

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

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
        int size = array.getInt(R.styleable.CustomView_custom_title_width, 3);
        a.recycle();
    }

    public CustomView(Context context) {
        super(context);
    }
}

コンストラクタで渡されるAttributeSetからレイアウトファイルで定義した属性値を取得することができます。

context.obtainStyledAttributes()は、引数にAttributeSetint[]をとり、int[]はarrtibuteのid配列を指しています。

これを指定する定数は、R.styleable.[※1独自クラス名]で参照することができます。

TypedArrayクラスのgetInt(int index, int defValue)は、 第一引数にTypedeArrayのindexを渡しますが、ここには、取得したいarrtibuteの属性のindexを指定します。

指定する定数は、R.styleable.[※1独自クラス名]_[※2属性名]で参照することが可能です。

※1 res/values/attrs.xml<declare-styleable>タグのname属性 

※2 res/values/attrs.xml<attr>タグのname属性