Edited at

Buttonのelevationを設定する方法

More than 3 years have passed since last update.


はじめに

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>