2015年5月29日金曜日

Androidでボタンの色を動的に変更する


Androidでボタンの背景をShapeで作って、その色をコードから動的に変化させるためのメモです。

ボタンをおした時やフォーカスが当たった時の変化に対応しています。




1. 全体のレイアウト


適当にボタンを作っただけです。 android:background=”@drawable/button_background”でボタンの背景を指定しています。


       <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"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            tools:context=".MainActivity">

        <Button
                android:id="@+id/button1"
                android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/button_background"
            android:text="Button1"/>

    </RelativeLayout>

2. ボタンの背景用Shape


ボタンが押されたとき、フォーカスがあるとき、ボタンが押されていないときの順番で定義しています。順番は次の手順で必要になります。


1.で設定したファイル名に合わせて、drawableの直下にbutton_background.xmlというファイル名で作成しています。


初期の色は適当です。それぞれの状態ごとに本体部分の色と枠線の色を定義しています。


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

    <!-- ボタンが押されたときの定義 -->
    <item android:state_pressed="true">
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <solid
                android:color="#0000FF"/>
            <stroke
                android:width="1dp"
                android:color="#00FF00"/>
            <corners
                android:radius="5dp"/>
        </shape>
    </item>

    <!-- フォーカスがあるときの定義 -->
    <item android:state_focused="true">
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <solid
                android:color="#FF0000"/>
            <stroke
                android:width="1dp"
                android:color="#00FF00"/>
            <corners
                android:radius="5dp"/>
        </shape>
    </item>

    <!-- ボタンが押されていないときの定義 -->
    <item android:state_pressed="false">
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <solid
                android:color="#FF0000"/>
            <stroke
                android:width="1dp"
                android:color="#FF0000"/>
            <corners
                android:radius="5dp"/>
            />
        </shape>
    </item>
</selector>

3. ボタンの色を変更するコード


pushedDrawable,focusedDrawable,unselectedDrawableが状態ごとの背景です。Shapeを定義した順番で取得できます。


GradientDrawable.setStroke()で枠線の太さと色を、GradientDrawable.setColor()で本体部分の色を変更しています。


Button button = (Button) findViewById(R.id.button1);
    StateListDrawable background = (StateListDrawable) button.getBackground();
    DrawableContainer.DrawableContainerState containerStateDrawable = (DrawableContainer.DrawableContainerState) background
            .getConstantState();
    Drawable[] children = containerStateDrawable.getChildren();

    GradientDrawable pushedDrawable = (GradientDrawable) children[0];
    GradientDrawable focusedDrawable = (GradientDrawable) children[1];
    GradientDrawable unselectedDrawable = (GradientDrawable) children[2];

    pushedDrawable.setColor(Color.GRAY);
    pushedDrawable.setStroke(10, Color.CYAN);

    focusedDrawable.setColor(Color.CYAN);
    focusedDrawable.setStroke(10,Color.GRAY);

    unselectedDrawable.setColor(Color.MAGENTA);
    unselectedDrawable.setStroke(10, Color.YELLOW);

getBackground()でDrawableを変数に取得して、変数の中身を探すという方法で調べたので、すごく時間がかかりました。


調べ終わってから検索して以下のページを見つけました。全て書いてあります。

How can I change colors in my StateListDrawable? - stackOverflow

http://stackoverflow.com/questions/19864337/how-can-i-change-colors-in-my-statelistdrawable


Written with StackEdit.