Android 5.0 android:elevation 适用于 View,但不适用于 Button?

Posted

技术标签:

【中文标题】Android 5.0 android:elevation 适用于 View,但不适用于 Button?【英文标题】:Android 5.0 android:elevation Works for View, but not Button? 【发布时间】:2015-01-20 17:15:32 【问题描述】:

在 SDK 管理器的 android 5.0 示例中,有 ElevationBasic 示例。它显示了两个View 对象:一个圆形和一个正方形。圈子已将android:elevation 设置为30dp

<?xml version="1.0" encoding="utf-8"?>
<!--
 Copyright 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.
-->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_
             android:layout_>
    <View
            android:id="@+id/floating_shape"
            android:layout_
            android:layout_
            android:layout_marginRight="40dp"
            android:background="@drawable/shape"
            android:elevation="30dp"
            android:layout_gravity="center"/>
    <View
            android:id="@+id/floating_shape_2"
            android:layout_
            android:layout_
            android:layout_marginLeft="25dp"
            android:background="@drawable/shape2"
            android:layout_gravity="center"/>
</FrameLayout>

在 Nexus 9 上,按原样运行示例,我们会在圆圈上看到阴影:

如果我们将小部件类更改为Button,保留所有其他属性不变,我们将失去圆圈上的阴影:

问题:

    为什么android:elevation 的行为会发生变化?不可能是因为背景,因为这两种情况的背景是一样的。

    哪些类支持android:elevation,哪些不支持?例如,使用TextView 而不是ViewButton 仍然会给我们阴影,因此这种行为变化不是在TextView 级别引入,而是在Button 级别引入。

    从昨天的this question 中可以看出,我们如何让android:elevationButton 上获得荣誉?是否有一些 android:allowElevationToWorkAsDocumented="true" 值需要我们添加到主题或其他内容中?

【问题讨论】:

有趣的问题和发现,您可以与我们分享测试项目的任何更改吗? @Rolfツ:同样,它是 Android 5.0 示例中的 ElevationBasic 示例,您可以从 SDK 管理器下载。我没有编写示例,尽管我按照Button 测试的问题中所述对其进行了修改。 我的错,我读得有点快;) 【参考方案1】:

Material 下的默认 Button 样式有一个 StateListAnimator,用于控制 android:elevationandroid:translationZ 属性。您可以删除现有的动画师或使用android:stateListAnimator 属性设置自己的动画师。

<Button
    ...
    android:stateListAnimator="@null" />

<Button
    ...
    android:stateListAnimator="@anim/my_animator" />

默认动画师在button_state_list_anim_material.xml 中定义。这是一个显示启用和按下状态的示例:

<?xml version="1.0" encoding="utf-8"?>
<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>
    ...
</selector>

【讨论】:

谢谢!这使得扁平按钮可以在 L 之前的设备上看起来相同。 @CommonsWare 嗨,我用过这个,但它没有显示任何帮助? 老兄,你救了我的命,通过使用 android:stateListAnimator="@null" 我修复了 z-order 的所有问题 动画师重写这些值在很多层面上都是错误的...... :( 开发人员完全不知道为什么按钮有不同的高度或 z 平移【参考方案2】:

根据我在 Lollipop 设备上运行 Appcompat v7 的经验,Button 可使用默认功能,如波纹效果、高程和 z 动画单击,但如果设置了个性化的 android:background 属性(如颜色或选择器),则会错过它们) 在 xml 元素中。

【讨论】:

这个问题是关于原生 Android 5.0 的实现,而不是appcompat-v7。不过谢谢! 可能是一样的,appcompat v7如果在Android 5上运行,会通过Platform主题从Material继承样式。 这里也一样,如果有人知道答案,那会很有帮助!【参考方案3】:

这是因为您正在手动设置按钮的背景,这将替换其所有效果。

AppCompat23.0.0 版本开始,有一个新的 Widget.AppCompat.Button.Colored 样式使用您的主题的 colorButtonNormal 为禁用颜色,colorAccent 为启用颜色。

    <Button
  ...
  style="@style/Widget.AppCompat.Button.Colored" />

如果您想要与指定不同的颜色,您可以创建一个新主题并通过android:theme 将其应用于按钮。然后你可以在你想要相同效果的所有按钮上使用这个主题。

【讨论】:

这个问题是关于原生 Android 5.0 的实现,而不是appcompat-v7。不过谢谢! @Heisenberg 我尝试添加它,但它不会在图像按钮上添加阴影。有小费吗?我试过使用原生 ImageButton 和 AppCompatImageButton。在 6.0 上进行测试。【参考方案4】:

我有一个类似的问题,我认为是由于错误地膨胀的布局,但似乎添加 clipToPadding 可以解决问题。 这必须设置为包含要投射阴影的视图的父 ViewGroup

... android:clipToPadding="false" ...

【讨论】:

【参考方案5】:

此解决方案适用于 Android 的所有 API 版本

创建阴影@android:drawable/dialog_holo_light_frame & 如果您想自定义背景颜色而不是白色,请在阴影顶部创建一个可自定义颜色的图层列表背景,如下所示

创建一个单独的可绘制文件 white_background_shadow.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--the shadow comes from here-->
    <item
        android:bottom="0dp"
        android:drawable="@android:drawable/dialog_holo_light_frame"
        android:left="0dp"
        android:right="0dp"
        android:top="0dp">

    </item>

    <item
        android:bottom="0dp"
        android:left="0dp"
        android:right="0dp"
        android:top="0dp">
        <!--whatever you want in the background, here i preferred solid white -->
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />

        </shape>
    </item>
</layer-list>

并像这样使用这个drawable作为背景

android:background="@drawable/shadow"

【讨论】:

以上是关于Android 5.0 android:elevation 适用于 View,但不适用于 Button?的主要内容,如果未能解决你的问题,请参考以下文章

Android 5.0五大安全特性

android 5.0 水波纹 实现

android 用代码打开 gprs(流量开关) android 5.0 ROOT

android 用代码打开 gprs(流量开关) android 5.0 ROOT

Android如何实现5.0以上图片沉浸式状态栏

Android 5.0 行为变更