Buttonのelevationを設定する方法

  • 32
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

Android5.0からはView部品に勝手に影がつくよ!という話なので、早速試してみました。
しかしButtonandroid:elevation="20dp"なんて設定してみたけれど、思ったような影が描画されません。どうすればいいんだろう?と悩んだ話です。

スクリーンショット

BeforeScreenShot.png

レイアウトXML

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

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="5dp shadow TextView"
        android:background="@android:color/holo_orange_light"
        android:elevation="5dp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="20dp shadow TextView"
        android:background="@android:color/holo_orange_light"
        android:elevation="20dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="5dp shadow Button"
        android:elevation="5dp"
        android:layout_below="@+id/textView"
        android:layout_alignParentStart="true"
        android:layout_alignEnd="@+id/textView" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="20dp shadow Button"
        android:elevation="20dp"
        android:layout_alignTop="@+id/button"
        android:layout_alignStart="@+id/textView2"
        android:layout_alignEnd="@+id/textView2" />

</RelativeLayout>

原因

こういった時はButtonのデフォルトのスタイルを確認すれば良いかという事で、android-21\data\res\values\styles_material.xmlを参照してみると、

styles_material.xml
    <!-- Bordered ink button -->
    <style name="Widget.Material.Button">
        <item name="background">@drawable/btn_default_material</item>
        <item name="textAppearance">?attr/textAppearanceButton</item>
        <item name="minHeight">48dip</item>
        <item name="minWidth">88dip</item>
        <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
        <item name="focusable">true</item>
        <item name="clickable">true</item>
        <item name="gravity">center_vertical|center_horizontal</item>
    </style>

<item name="stateListAnimator">@anim/button_state_list_anim_material</item>というヤツがなんだか怪しい。このbutton_state_list_anim_material.xmlを確認すると、

button_state_list_anim_material.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:state_enabled="true">
        <set>
            <objectAnimator android:propertyName="translationZ"
                            android:duration="@integer/button_pressed_animation_duration"
                            android:valueTo="@dimen/button_pressed_z_material"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="elevation"
                            android:duration="0"
                            android:valueTo="@dimen/button_elevation_material"
                            android:valueType="floatType"/>
        </set>
    </item>
    <!-- base state -->
    <item android:state_enabled="true">
        <set>
            <objectAnimator android:propertyName="translationZ"
                            android:duration="@integer/button_pressed_animation_duration"
                            android:valueTo="0"
                            android:startDelay="@integer/button_pressed_animation_delay"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="elevation"
                            android:duration="0"
                            android:valueTo="@dimen/button_elevation_material"
                            android:valueType="floatType" />
        </set>
    </item>
    <item>
        <set>
            <objectAnimator android:propertyName="translationZ"
                            android:duration="0"
                            android:valueTo="0"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="elevation"
                            android:duration="0"
                            android:valueTo="0"
                            android:valueType="floatType"/>
        </set>
    </item>
</selector>

こ れ だ !

objectAnimatorelevationを変更しているため、いくら設定した所でこの値で上書きされてしまっていると思われます。

解決策

というわけで、解決策としてはButtonStateListAnimatorを設定し直せば良いと思われます。

今回はbutton_state_list_anim_material.xmlを丸々コピーして、パラメータだけ変更したStateListAnimatorを新たに作って設定しました。(button_state_list_anim_material_20dp.xmlは省略します)

スクリーンショット

AfterScreenShot.png

レイアウトXML

button_state_list_anim_material_5dp.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:state_enabled="true">
        <set>
            <objectAnimator android:propertyName="translationZ"
                            android:duration="100"
                            android:valueTo="2dp"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="elevation"
                            android:duration="0"
                            android:valueTo="1dp"
                            android:valueType="floatType"/>
        </set>
    </item>
    <!-- base state -->
    <item android:state_enabled="true">
        <set>
            <objectAnimator android:propertyName="translationZ"
                            android:duration="100"
                            android:valueTo="0"
                            android:startDelay="100"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="elevation"
                            android:duration="0"
                            android:valueTo="5dp"
                            android:valueType="floatType" />
        </set>
    </item>
    <item>
        <set>
            <objectAnimator android:propertyName="translationZ"
                            android:duration="0"
                            android:valueTo="0"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="elevation"
                            android:duration="0"
                            android:valueTo="0"
                            android:valueType="floatType"/>
        </set>
    </item>
</selector>
activity_main.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" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="5dp shadow TextView"
        android:background="@android:color/holo_orange_light"
        android:elevation="5dp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="20dp shadow TextView"
        android:background="@android:color/holo_orange_light"
        android:elevation="20dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="5dp shadow Button"
        android:elevation="5dp"
        android:layout_below="@+id/textView"
        android:layout_alignParentStart="true"
        android:layout_alignEnd="@+id/textView"
        android:stateListAnimator="@anim/button_state_list_anim_material_5dp"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="20dp shadow Button"
        android:elevation="20dp"
        android:layout_alignTop="@+id/button"
        android:layout_alignStart="@+id/textView2"
        android:layout_alignEnd="@+id/textView2"
        android:stateListAnimator="@anim/button_state_list_anim_material_20dp"/>

</RelativeLayout>