くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

レイアウトの背景をカスタマイズする

今回はレイアウトファイルで、背景をカスタマイズする場合の方法についてです

レイアウトで枠線をつけたり、角丸にしたりカスタマイズしたい場合Attributesで設定できるものもあれば、設定できないものもあります

そして、設定できない場合にはxmlファイルを利用することで画像を用意しなくてもボタンの角を丸くしたり、レイアウトにグラデーションをつけたりすることができます

作成するファイルはres/drawableフォルダに格納します。 drawableは背景画像の設定やグラデーションの設定などを格納していくフォルダです。 drawableフォルダ内に新たな設定用のxmlファイルを作って呼び出します。

このフォルダは本来、端末の画面解像度に関係なく、すべての端末から参照させたい場合のものを格納しておくところです(あと画像を格納します)

カスタムドローワブルには多くの種類があります。今回はよく使うものを抜粋して説明します

全てを確認する場合には参照に記載している公式ドキュメントを確認してください

Shape

まずはShapeドローワブルです

shapeドローワブルはBitmapなどの画像そのものを使わずにグラフィック的な画像を表現するものです。 円や四角形など単純なものに使います

shapeドローワブルは<shape>を使って作成します。一例ですが、次のように使います(今回はradius_button.xmlというファイル名で作成しています)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#fff123" />
    <corners android:radius="10dp" />
</shape>

shapeでは以下の4種類の形状が用意されています

  • rectangle : 四角形
  • oval : 楕円
  • line : 直線
  • ring : 円形

そして、上記例ではsolidcornersを定義しています

solidは背景色、cornersは角丸を定義しています

子要素として設定できる項目は数が多いので参照に記載している公式ドキュメントを参照してください

ここまででShapeドローワブルを作成しましたが、レイアウトに適用させるためには次のようにandroid:backgroundに設定することで適用できます

<Button
        android:id="@+id/selectorButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/radius_button"
        android:text="Radius Button By Selector"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/backgroundNullButton" />

また、次のようにImageViewにも適用できるため画像よりリソースを省略できることもあります

<ImageView
        android:id="@+id/selectorImageView"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="10dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button"
        app:srcCompat="@drawable/radius_button" />

適用したものをビルドすると次のようになります

layer-list

次にlayer-listドローワブルです

layer-listは要素を重ねあわせて使います。画像などをレイヤー構成で重ねることができるリソースで、複数の画像をひとつのリソースとして取り扱うことができます

作成する場合には<layer-list>タグを使用します。今回は、画像を入れたplaceholderを作成します

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimary" />
            <size
                android:width="100dp"
                android:height="100dp" />
        </shape>
    </item>
    <item
        android:width="24dp"
        android:height="24dp"
        android:drawable="@drawable/ic_home_black_24dp"
        android:gravity="center" />
</layer-list>

itemタグが2つの構成になっていると思います。 レイアウトの時と同じで下の方が前面に表示されます。 なので、画像が前面に表示されて、その後ろに四角で背景色がcolorPrimaryの画像が重なっている構成になります

placeholder用の画像だけ用意してもらい、Drawableで必要サイズの画像を用意してしまえば、 画像分の容量が削減でき、デザイナーの負担も減ると思います。

この作成したドローワブルをShapeの時と同じようにbackgroundに設定すれば背景に反映されます

また、これで作成した画像はscaleType="fitXY"で配置すると、伸縮するのが背景色部分になり、ロゴのサイズ自体は変わりません。 これで画像を用意する必要が減ると思います。

Selector

次にSelectorドローワブルです

Selectorドローワブルはオブジェクトの状態に応じて、複数の異なる画像を使用して同じグラフィックを表します。 今回はボタンを押した時と押していない時で表示を分けるドローワブルを作成します

Selectorドローワブルは<selector>タグを使用します

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape android:shape="rectangle">
            <corners
                android:radius="10dp"/>
            <solid
                android:color="#cccccc"/>
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners
                android:radius="10dp"/>
            <solid
                android:color="#fff123"/>
        </shape>
    </item>
</selector>

2つのitemがありますが、2つが重なっているというよりは条件で表示を分岐させているイメージが近いかもしれません

state_pressedがボタンを押しているか押していないかを判定する値で、プッシュ状況で表示を変えています

この作成したドローワブルをbackgroundに設定すれば背景に反映され、タップした時に背景が変更されます

ripple

最後にRippleドローワブルです

Rippleドローワブルはタップしたとき波形で視覚的にタップしたのがわかるようなものです(RippleEffectともいいます)

Rippleドローワブルは<ripple>タグを使用します

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
    <!-- 波紋の色 -->
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#000000" />
            <corners android:radius="3dp" />
        </shape>
    </item>
    <!-- ボタンの背景-->
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimary" />
        </shape>
    </item>
</ripple>

Rippleタグに指定するのは波紋の色で、これにより白いボタンに青い波紋を広げるなどのカスタマイズが出来ます

maskには波紋が広がる範囲を指定します。(android:id="@android:id/mask"の部分) maskは指定しなかった場合、 適用したレイアウトの範囲を超えて波紋が広がるので注意が必要です。 波紋が広がる範囲はα値で決定されるため、背景が透明のボタンの場合、maskを指定しないとRipple Effect効果は適用されません。 また、単なるShapeのほかに透過pngによるbitmapも指定可能で、複雑な形に波紋エフェクトをかけることも出来ます。

あとは作成したドローワブルを適用したいオブジェクトのBackgroundに指定することでRippleEffectを実現することが出来ます

※ボタンにRippleを適用する場合には次のようにandroid:background="?attr/selectableItemBackground"を指定することでデフォルトのRippleEffectが適用されます。 背景色などでbackgroundに他の値を指定している場合にはforegroundに指定しましょう

<Button
        android:id="@+id/button12"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:text="Default Ripple"
        android:background="?attr/selectableItemBackground"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="parent" />

まとめ

カスタムドローワブルについて説明しましたが、今回紹介したものはまだほんの一部なので公式ドキュメントを確認していろんなパターンを試してください

また、MaterialComponentだと角丸など設定できる項目が増えているかもしれないので確認して必要に応じて使うようにしましょう

参照

qiita.com

developer.android.com

developer.android.com