Android“高程”未显示阴影


273

我有一个ListView,对于每个列表项,我希望它在其下方显示一个阴影。我正在使用Android Lollipop的新高程功能在要投射阴影的View上设置Z,并且已经使用ActionBar(在技术上是Lollipop中的工具栏)有效地做到了这一点。我正在使用棒棒糖的高程,但是由于某些原因,它在列表项下没有显示阴影。这是设置每个列表项的布局的方式:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    style="@style/block"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/lightgray"
    >

    <RelativeLayout
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_marginLeft="40dp"
        android:layout_marginRight="40dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:elevation="30dp"
        >

        <ImageView
            android:id="@+id/documentImageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop" />

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/alphared"
            android:layout_alignParentBottom="true" >

            <appuccino.simplyscan.Extra.CustomTextView
                android:id="@+id/documentName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                app:typeface="light"
                android:paddingLeft="16dp"
                android:paddingTop="8dp"
                android:paddingBottom="4dp"
                android:singleLine="true"
                android:text="New Document"
                android:textSize="27sp"/>

            <appuccino.simplyscan.Extra.CustomTextView
                android:id="@+id/documentPageCount"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                app:typeface="italic"
                android:paddingLeft="16dp"
                android:layout_marginBottom="16dp"
                android:text="1 page"
                android:textSize="20sp"/>

        </LinearLayout>

    </RelativeLayout>

</RelativeLayout>

但是,这是显示列表项而不显示阴影的方式: 在此处输入图片说明

我也尝试了以下无济于事:

  1. 将高程设置为ImageView和TextViews本身,而不是父级布局。
  2. 将背景应用于ImageView。
  3. 使用TranslationZ代替高程。

我尝试了您的布局(没有customviews),并在手机中显示了阴影,您能否共享一个最小的项目来重现问题?
rnrneverdies 2014年


Answers:


383

我一直在玩棒棒糖上的阴影,这是我发现的:

  1. 父母ViewGroup的界限似乎出于某种原因切断了子女的阴影。和
  2. 用设置的阴影android:elevation是通过View的边界截取的,而不是通过边距延伸的边界;
  3. 使子视图显示阴影的正确方法是在父级上设置填充,并android:clipToPadding="false"在该父级上设置填充。

根据我的了解,这是我对您的建议:

  1. 将顶层设置RelativeLayout为具有等于您要在其上显示阴影的相对布局上设置的边距的填充;
  2. 设置android:clipToPadding="false"在相同的RelativeLayout;
  3. RelativeLayout也已设置高程的中删除边距;
  4. [编辑]您可能还需要在需要提升的子布局上设置非透明背景色。

最终,您的顶级相对布局应如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/block"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/lightgray"
    android:paddingLeft="40dp"
    android:paddingRight="40dp"
    android:paddingTop="20dp"
    android:paddingBottom="20dp"
    android:clipToPadding="false"
    >

内部相对布局应如下所示:

<RelativeLayout
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:background="[some non-transparent color]"
    android:elevation="30dp"
    >

8
谢谢你!我还发现将android:clipChildren =“ false”应用于父级相对布局时很有用。
blaffie 2015年

1
很高兴为@blaffie提供帮助!
贾斯汀·波拉德

214
令人讨厌的是Google产生了这样的伪劣代码。多年来,我们将不得不解决这些框架错误。
miguel 2015年

8
Google只说(alas):“ 阴影是由高位视图的父级绘制的,因此受标准视图裁剪的限制,默认情况下,父级会对其进行裁剪。 ”。
约翰

5
就我而言,它是透明的颜色。好吧,透明的东西不会蒙上阴影...哈哈
Ferran Maylinch '16

285

如果您没有背景视图,此行将为您提供帮助

android:outlineProvider="bounds"

默认情况下,阴影由视图的背景决定,因此,如果没有背景,也将没有阴影。


11
预览是一件奇怪的事,它显示了标高,但实际设备却没有。谢谢,这个解决了这个问题。
Ioane Sharvadze '16

适用于API级别21和更高级别的作品
Pantelis Ieronimakis

10
这种方法对我有用,但是在应用于textview时在侧面提供了对角线边框。将背景设置为一种颜色(与父级背景颜色相同)效果更好。
Gober

4
如果您的背景是自定义的且没有背景,这也适用<solid>
David Lord

可以反向使用。当您想要具有高程的不透明背景并且不希望有阴影时。只需将其设置为即可none。谢谢!
奥德斯

101

显然,您不能仅在视图上设置高程并显示它。您还需要指定背景。

添加到我的LinearLayout的以下行终于显示了阴影:

android:background="@android:color/white"
android:elevation="10dp"

真是出乎意料。我已经将ImageView设置为src并正在寻找解决方案。谢谢。
安德鲁·格罗

47

您应该注意的另一件事是,如果清单中有此行,则阴影不会显示:

android:hardwareAccelerated =“ false”

我尝试了所有建议的内容,但仅当我删除该行时,它才对我有用,我拥有该行的原因是因为我的应用程序可以处理许多位图图像,并且它们导致应用程序崩溃。


1
如果您需要该标志,这不能解决问题。
克莱夫·杰佛瑞斯

谢谢!!我花了一天的时间尝试提升AppBar,并在检查清单中的该活动标志时发现了问题
ir2pid

1
我尝试了所有可能的解决方案,但对我没有任何帮助。此解决方案有效。谢谢。也需要android:clipToPadding="false"与此解决方案。
Chirag Savsani

29

如果您没有背景视图,此行将为您提供帮助

android:outlineProvider="bounds"

如果您有背景视图,此行将为您提供帮助

android:outlineProvider="paddedBounds"

6
此解决方案是唯一对我有效的解决方案。谢谢
Oleh Liskovych '18

4
除非您在视图背景上具有半径,否则此方法将起作用,在这种情况下,阴影将显示为矩形显示,但pappedBounds确实适用于具有背景的视图。
Trevor Hart

android:outlineProvider="paddedBounds"这条线对我有用。我设置了Selector Drawable。
Chirag Savsani

1
当我使用它时,阴影完全在视图内部而不是外部绘制,这不是我想要的。
androidguy


12

gh,花了一个小时试图弄清楚。在我的情况下,我有一个背景设置,但是设置为一种颜色。这还不够,您需要将视图的背景设置为可绘制的。

例如:这不会有阴影:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="165dp"
    android:background="@color/ight_grey"
    android:elevation="20dp"
    android:orientation="vertical"
    />

但这会

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="165dp"
    android:background="@drawable/selector_grey"
    android:elevation="20dp"
    android:orientation="vertical"
    />

编辑:还发现,如果您使用选择器作为背景,如果您没有设置拐角,则阴影将不会显示在“ 预览”窗口中,但会显示在设备上

例如,这在预览中没有阴影:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white" />
            <stroke
                android:width="1dp"
                android:color="@color/grey"/>
        </shape>
    </item>
</selector>

但是这样做:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white" />
            <corners android:radius="1dp" />
            <stroke
                android:width="1dp"
                android:color="@color/grey"/>
        </shape>
    </item>
</selector>

1
在RecyclerView项目中,我的观点与您的观点完全相反...令人惊讶的是,经过5年的专业Android开发,我仍然找到必须与这些API进行对抗的案例:(
aProperFox

7

添加背景色对我有所帮助。

<CalendarView
    android:layout_width="match_parent"
    android:id="@+id/calendarView"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"
    android:layout_height="wrap_content"
    android:elevation="5dp"

    android:background="@color/windowBackground"

    />

4

有时候喜欢background="@color/***"还是background="#ff33**"不行,我background_color用drawable 代替,然后就行了



3

如果您想要透明的背景并且android:outlineProvider="bounds"不适用于您,则可以创建自定义ViewOutlineProvider:

class TransparentOutlineProvider extends ViewOutlineProvider {

    @Override
    public void getOutline(View view, Outline outline) {
        ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
        Drawable background = view.getBackground();
        float outlineAlpha = background == null ? 0f : background.getAlpha()/255f;
        outline.setAlpha(outlineAlpha);
    }
}

并将此提供程序设置为您的透明视图:

transparentView.setOutlineProvider(new TransparentOutlineProvider());

来源:https//code.google.com/p/android/issues/detail?id = 78248#c13

[编辑] Drawable.getAlpha()的文档说,它特定于Drawable如何威胁Alpha。可能总是返回255。在这种情况下,您可以手动提供alpha:

class TransparentOutlineProvider extends ViewOutlineProvider {

    private float mAlpha;

    public TransparentOutlineProvider(float alpha) {
        mAlpha = alpha;
    }

    @Override
    public void getOutline(View view, Outline outline) {
        ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
        outline.setAlpha(mAlpha);
    }
}

如果您的视图背景是带有默认颜色#DDFF0000的StateListDrawable,它具有alpha DDx0 / FFx0 == 0.86

transparentView.setOutlineProvider(new TransparentOutlineProvider(0.86f));

2

给我工作的布局提供一些背景颜色,例如:

    android:background="@color/catskill_white"
    android:layout_height="?attr/actionBarSize"
    android:elevation="@dimen/dimen_5dp"

1

clipChildren="false"在父级布局上的设置有些运气。


1

我花了一些时间进行处理,最后才意识到,当背景较暗时,看不到阴影


1

除了接受的答案外,还有另一个原因,如果手机上的Bluelight滤镜功能打开,则海拔可能无法按预期工作。

当我的设备中的海拔高度完全扭曲且无法忍受时,我正面临着这个问题。但是在预览中,海拔高度很好。关闭手机上的Bluelight筛选器可以解决此问题。

所以即使设定

android:outlineProvider="bounds"

海拔高度无法正常工作,那么您可以尝试修改手机的颜色设置。


0

我认为您的问题源于以下事实:您已将height元素应用于填充其父级的相对布局。它的父级将所有子级视图剪辑在其自己的绘图画布中(并且是处理子级阴影的视图)。您可以通过RelativeLayout在视图xml 的最顶层(根标记)中应用一个height属性来解决此问题。


0

就我而言,字体是个问题。

1)没有fontFamily我需要设置android:background一些值。

<TextView
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:background="@android:color/white"
    android:elevation="3dp"
    android:gravity="center"
    android:text="@string/fr_etalons_your_tickets"
    android:textAllCaps="true"
    android:textColor="@color/blue_4" />

2)与fontFamily我不得不添加android:outlineProvider="bounds"设置:

<TextView
    android:fontFamily="@font/gilroy_bold"
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:background="@android:color/white"
    android:elevation="3dp"
    android:gravity="center"
    android:outlineProvider="bounds"
    android:text="@string/fr_etalons_your_tickets"
    android:textAllCaps="true"
    android:textColor="@color/blue_4" />

0

就我而言,这是由于自定义父组件将渲染层类型设置为“软件”引起的:

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

删除这一行的技巧。或者当然,您需要首先评估为什么要这样做。就我而言,这是为了支持Honeycomb,它远远落后于我项目的当前最低SDK。


0

还要检查您是否在该视图上不更改Alpha。当我在某些视图中使用高程更改Alpha时,我正在调查问题。当更改alpha并将其更改回1f时,它们只是松开了标高。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.