アプリケーション開発ポータルサイト
ServerNote.NET
Amazon.co.jpでPC関連商品タイムセール開催中!
カテゴリー【AndroidJava
【Android】Buttonが常に最前面に来る問題を回避してボタンに画像を重ねる
POSTED BY
2023-07-13

単純なものならButtonにdrawableLeft等を指定すればよいが、複雑なカスタムボタンはFrameLayoutやRelativeLayoutを使ってButtonにImageViewを重ねてレイアウトすることがよくある。
画像の一番上のボタンは以下のようにレイアウトしている。

XMLlayout/arrow_button_under_api21.xmlGitHub Source
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/arrow_button_under_api21"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center">

    <Button
        android:id="@+id/arrow_button_under_api21_button"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:background="@drawable/round_gray_w"
        android:gravity="center"
        android:minWidth="0dp"
        android:minHeight="0dp"
        android:padding="8dp"
        android:text="選択してください"
        android:textColor="@color/white"
        android:textSize="16dp" />

    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:src="@drawable/arrow_down" />
</RelativeLayout>

RelativeLayoutを使ってButtonの次にImageを重ねているのにもかかわらず、Imageが表示されていない。これはAPI LEVEL 21 = Lolipop 以上の時に起きる現象で、それ未満の場合は2番目のボタンのように正常にImageが左に出現する。

Lolipop以上の場合、Buttonに
android:stateListAnimator="@null"
を指定(影を無効にする)すれば、2番目のボタンのようにImageがちゃんと表示される。

XMLlayout/arrow_button_after_api21.xmlGitHub Source
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/arrow_button_after_api21"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center">

    <Button
        android:id="@+id/arrow_button_after_api21_button"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:background="@drawable/round_gray_w"
        android:gravity="center"
        android:minWidth="0dp"
        android:minHeight="0dp"
        android:padding="8dp"
        android:stateListAnimator="@null"
        android:text="選択してください"
        android:textColor="@color/white"
        android:textSize="16dp" />

    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:src="@drawable/arrow_down" />
</RelativeLayout>

しかしこの命令はLolipop以降にしか存在しないため、minSdkVersion が 21未満の端末で実行しようとすると落ちる。よって21未満をサポートするならXMLでなくコードでバージョンにより処理を入れる必要があるが、setContentViewした後では効かない場合があり現実的ではない。

Button button = (Button)findViewById( R.id.button );
if( Build.VERSION.SDK_INT < 21 ){
    button.stateListAnimator = null; //addViewされたボタンには効かない?
}

なのでここからが本題だが、上記問題いずれにも対応するには、Buttonを使わずにTextViewとselectorの組み合わせでボタンを作ってしまえばよい。それが画像の一番下のボタンである。以下のように作成する。

XMLlayout/arrow_button.xmlGitHub Source
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/arrow_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/selector_round_gray_w"
    android:clickable="true">

    <TextView
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="8dp"
        android:text="選択してください"
        android:textColor="@drawable/selector_color_black"
        android:textSize="16dp" />

    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:src="@drawable/arrow_down" />
</RelativeLayout>

RelativeLayoutをclickableにしてselectorをbackgroundに作成。ButtonでなくTextViewにして、textColorをクリックに合わせて変えるselectorを作成。

XMLdrawable/selector_round_gray_w.xmlGitHub Source
<?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">
            <corners android:radius="10dp" />
            <solid android:color="@color/white" />
            <stroke android:width="1.5px" android:color="@color/white" />
        </shape>
    </item>
    <item android:state_pressed="false">
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <corners android:radius="10dp" />
            <solid android:color="@color/gray" />
            <stroke android:width="1.5px" android:color="@color/white" />
        </shape>
    </item>
</selector>

XMLdrawable/selector_color_black.xmlGitHub Source
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/black" android:state_pressed="true" />
    <item android:color="@color/white" android:state_pressed="false" />
</selector>

XMLvalues/colors.xmlGitHub Source
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="black">#000000</color>
    <color name="white">#ffffff</color>
    <color name="red">#c44857</color>
    <color name="pink">#e59087</color>
    <color name="green">#77acae</color>
    <color name="blue">#8686af</color>
    <color name="aquamarine">#7fffd4</color>
    <color name="palegreen">#98fb98</color>
    <color name="lightyellow">#f7efdb</color>
    <color name="yellow">#dcb654</color>
    <color name="darkyellow">#b8b05d</color>
    <color name="lightgray">#999999</color>
    <color name="gray">#808080</color>
    <color name="trans">#00ffffff</color>
    <color name="whitetrans">#99ffffff</color>
    <color name="blacktrans">#aa000000</color>
</resources>

drawable/arrow_down.png drawable/arrow_down.png

ポイントはTextViewのtextColorに指定するselectorは色のみを指定する訳なのでitem android:colorが必須であり、RelativeLayoutのbackgroundに指定するselectorは塗りつぶしを指定する訳なのでitem android:drawableもしくはsolidが必須である。

これでこのボタンは、タップした時に背景が白く、テキストが黒くハイライトするボタンとなる。

※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!
ご連絡は以下アドレスまでお願いします★

☆ServerNote.NETショッピング↓
ShoppingNote / Amazon.co.jp
☆お仲間ブログ↓
一人社長の不動産業務日誌
【キーワード検索】