はじめに
Android5.0からはView部品に勝手に影がつくよ!という話なので、早速試してみました。
しかしButton
にandroid:elevation="20dp"
なんて設定してみたけれど、思ったような影が描画されません。どうすればいいんだろう?と悩んだ話です。
スクリーンショット
レイアウト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
を参照してみると、
<!-- 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
を確認すると、
<?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>
こ れ だ !
objectAnimator
でelevation
を変更しているため、いくら設定した所でこの値で上書きされてしまっていると思われます。
解決策
というわけで、解決策としてはButton
のStateListAnimator
を設定し直せば良いと思われます。
今回はbutton_state_list_anim_material.xml
を丸々コピーして、パラメータだけ変更したStateListAnimatorを新たに作って設定しました。(※button_state_list_anim_material_20dp.xml
は省略します)
スクリーンショット
レイアウト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>
<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>