【问题标题】:Android - Shadow size not affected when changing elevationAndroid - 更改高度时阴影大小不受影响
【发布时间】:2020-02-23 23:32:11
【问题描述】:

我正在开发一个针对 android Lollipop 及更高版本的 Android 应用程序,我查看了海拔属性以在元素(即按钮、卡片和底部导航视图)下实现阴影。

我面临的问题是,在 XML 中更改 android:elevation 值时,阴影大小不受影响。我尝试并阅读的内容:

  • 我了解到,除非视图有背景,否则海拔不起作用,而我的背景确实有(发布在下面)。
  • 围绕 SO 的其他问题表明它们根本没有阴影,在我的情况下,视图下方确实有阴影,但其大小不受海拔属性的影响。

关于代码,您可以在下面找到我的按钮样式和片段的布局。

按钮样式

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:app="http://schemas.android.com/apk/res-auto">
    <style name="Search" parent="@android:style/Widget.Button">
        <item name="android:gravity">center_vertical|start</item>
        <item name="android:textColor">@color/lightText</item>
        <item name="android:textSize">@dimen/main_search_textSize</item>
        <item name="android:background">@drawable/main_search</item>
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
        <item name="android:text">@string/search</item>
        <item name="android:elevation">@dimen/main_search_elevation</item>
        <item name="android:drawableStart">@drawable/ic_main_search</item>
        <item name="android:paddingLeft">@dimen/main_search_padding</item>
        <item name="android:paddingRight">@dimen/main_search_padding</item>
        <item name="android:drawablePadding">@dimen/main_search_padding</item>
    </style>
</resources>

片段布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingStart="@dimen/activity_horizontal_margin"
    android:paddingEnd="@dimen/activity_horizontal_margin"
    android:background="@color/lightBackground"
    android:clipToPadding="false">

    <androidx.appcompat.widget.AppCompatButton
        style="@style/Search"
        android:layout_width="match_parent"
        android:layout_height="@dimen/main_search_height"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

dimens.xml

<resources>
    <dimen name="activity_horizontal_margin">24dp</dimen>
    <dimen name="activity_vertical_margin">24dp</dimen>

    <dimen name="main_nav_icon_padding">6dp</dimen>

    <dimen name="main_search_height">54dp</dimen>
    <dimen name="main_search_marginTop">72dp</dimen>
    <dimen name="main_search_elevation">24dp</dimen>
    <dimen name="main_search_padding">16dp</dimen>
    <dimen name="main_search_textSize">20sp</dimen>
</resources>

这就是我得到的(不管海拔属性是什么):

请注意,长按按钮时阴影会发生变化,并且不会以任何方式被剪裁。

因此,您知道问题出在哪里吗?

【问题讨论】:

  • 你能检查你的清单,如果你的 HardwareAcceleration 是真还是假?
  • 改用cardview
  • @FurqanKhan 也没有,它没有设置。将其设置为true 时,我得到了与上面相同的结果。当设置为false时,阴影一起消失了。

标签: android android-layout


【解决方案1】:

嘿,你的问题似乎很有用,所以我决定试一试。我希望这对你有帮助,如果有人有更好的方法发布它。

首先,我认为主要问题是您使用的按钮样式有一些StateListAnimator 控制按钮的高度,因此无论您设置什么值作为高度它都会被覆盖。最简单的解决方案是简单地添加

<item name="android:stateListAnimator">@null</item>

到您的自定义“搜索”样式,现在该按钮将显示您使用 &lt;item name="android:elevation"&gt;@dimen/main_search_elevation&lt;/item&gt; 以相同样式设置的海拔。

但这就像一个静态视图,当你点击或长按等时,它会给你一个提升的外观,但没有很酷的动画变化。

为了获得这些动画,您需要使用ObjectAnimator 创建您的自定义 StateListAnimator。我创建了一个作为示例。创建android资源目录animator并添加一个xml文件,您将在其中编写所需的自定义动画。

这是我创建的 custom_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!--For when your button is pressed-->
    <item
        android:state_enabled="true"
        android:state_pressed="true">
        <set>
            <objectAnimator
                android:duration="300"
                android:propertyName="translationZ"
                android:valueTo="12dp"
                android:valueType="floatType" />
            <objectAnimator
                android:duration="300"
                android:propertyName="elevation"
                android:valueTo="12dp"
                android:valueType="floatType" />
        </set>
    </item>

    <!--For when your button is in its normal state-->
    <item android:state_enabled="true">
        <set>
            <objectAnimator
                android:duration="300"
                android:propertyName="translationZ"
                android:valueTo="4dp"
                android:valueType="floatType" />
            <objectAnimator
                android:duration="300"
                android:propertyName="elevation"
                android:valueTo="4dp"
                android:valueType="floatType" />
        </set>
    </item>

</selector>

您需要根据您的要求设置自定义尺寸,以了解按钮何时处于其基本状态以及何时被按下。我分别使用了4dp12dp,因为这似乎绰绰有余

就是这样,现在你只需要将它作为 stateListAnimator 添加到你的样式中

    <item name="android:stateListAnimator">@animator/custom_animator</item>

它应该可以工作。请注意,在这种情况下android:elevation 将再次不起作用,只有在您的动画师中定义的值才会反映。因此,您可以删除 &lt;item name="android:elevation"&gt;@dimen/main_search_elevation&lt;/item&gt;,因为它不需要。

参考了一些关于媒体的博客和其他关于 SO 的帖子,以了解这一切是如何运作的。 试试这个,让我们知道它是否适合你。

【讨论】:

  • 你是对的。stateListAnimator 是罪魁祸首。但是我尝试了custom_animator,高度没有改变。另外,是否知道高程阴影是否可以移动(x,y)并改变其颜色?
  • 您是否确保其空闲状态和按下时的海拔值不同,否则没有明显差异。如果它仍然不起作用,您可以尝试将 propertyName 中的 "elevation" 更改为 "translationZ"。如果还是不行,您可以尝试将&lt;objectAnimator&gt;&lt;/objectAnimator&gt; 包装在&lt;set&gt;&lt;/set&gt; 中来组合两者。
  • 对于自定义阴影等,您可以参考this link,因为我没有太多经验。
  • 编辑了我的答案以同时使用两者,您的情况听起来像是将其设置为 null 时会发生什么。奇怪,我正在使用您在上面发布的 xml,它对我来说运行良好
  • 按住按钮时,阴影确实会增加到指定的新值。不确定是什么导致了您的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 2017-09-10
  • 2023-01-25
  • 2018-10-09
  • 1970-01-01
相关资源
最近更新 更多