Android “elevation” not showing a shadow

2019-01-01 14:33发布

问题:

I have a ListView, and with each list item I want it to show a shadow beneath it. I am using Android Lollipop\'s new elevation feature to set a Z on the View that I want to cast a shadow, and am already doing this effectively with the ActionBar (technically a Toolbar in Lollipop). I am using Lollipop\'s elevation, but for some reason it isn\'t showing a shadow under the list items. Here is how each list item\'s layout is set up:

<?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>

However, here is how it shows the list item, without a shadow: \"enter

I have also tried the following to no avail:

  1. Set the elevation to the ImageView and TextViews themselves instead of the parent layout.
  2. Applied a background to the ImageView.
  3. Used TranslationZ in place of Elevation.

回答1:

I\'ve been playing around with shadows on Lollipop for a bit and this is what I\'ve found:

  1. It appears that a parent ViewGroup\'s bounds cutoff the shadow of its children for some reason; and
  2. shadows set with android:elevation are cutoff by the View\'s bounds, not the bounds extended through the margin;
  3. the right way to get a child view to show shadow is to set padding on the parent and set android:clipToPadding=\"false\" on that parent.

Here\'s my suggestion to you based on what I know:

  1. Set your top-level RelativeLayout to have padding equal to the margins you\'ve set on the relative layout that you want to show shadow;
  2. set android:clipToPadding=\"false\" on the same RelativeLayout;
  3. Remove the margin from the RelativeLayout that also has elevation set;
  4. [EDIT] you may also need to set a non-transparent background color on the child layout that needs elevation.

At the end of the day, your top-level relative layout should look like this:

<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\"
    >

The interior relative layout should look like this:

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


回答2:

If you have a view with no background this line will help you

android:outlineProvider=\"bounds\"

By default shadow is determined by view\'s background, so if there is no background, there will be no shadow also.



回答3:

Apparently, you cannot just set an elevation on a View and have it appear. You also need to specify a background.

The following lines added to my LinearLayout finally showed a shadow:

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


回答4:

one other thing that you should be aware of, shadows will not show if you have this line in the manifest:

android:hardwareAccelerated=\"false\"

I tried all of the suggested stuff but it only worked for me when i removed the line, the reason i had the line was because my app works with a number of bitmap images and they were causing the app to crash.



回答5:

If you are adding elevation to a button element, you need to add the following line:

android:stateListAnimator=\"@null\"

See Android 5.0 android:elevation Works for View, but not Button?



回答6:

Ugh, just spent an hour trying to figure this out. In my case I had a background set, however it was set to a color. This is not enough, you need to have the background of the view set to a drawable.

e.g. This won\'t have a shadow:

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

but this will

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

EDIT: Have also discovered that if you use a selector as a background, if you don\'t have the corner set then the shadow won\'t show up in the Preview window but it will show up on the device

e.g. This doesn\'t have a shadow in preview:

<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>

but this does:

<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>


回答7:

If you have a view with no background this line will help you

android:outlineProvider=\"bounds\"

If you have a view with background this line will help you

android:outlineProvider=\"paddedBounds\"


回答8:

Adding background color helped me.

<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\"

    />


回答9:

If you want to have transparent background and android:outlineProvider=\"bounds\" doesn\'t work for you, you can create custom 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);
    }
}

And set this provider to your transparent view:

transparentView.setOutlineProvider(new TransparentOutlineProvider());

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

[EDIT] Documentation of Drawable.getAlpha() says that it is specific to how the Drawable threats the alpha. It is possible that it will always return 255. In this case you can provide the alpha manually:

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);
    }
}

If your view background is a StateListDrawable with default color #DDFF0000 that is with alpha DDx0/FFx0 == 0.86

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


回答10:

sometimes like background=\"@color/*\" or background=\"#ff33\"not work, I replace background_color with drawable, then it works



回答11:

give some background color to layout worked for me like:

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


回答12:

Adding to the accepted answer, there is one more reason due to which elevation may not work as expected.

If the Bluelight filter feature on the phone is ON

I was facing this issue when the elevation appeared completely distorted and unbearable in my device. But the elevation was fine in the preview. Turning off the Bluelight filter on phone resolved the issue.

So even after setting

android:outlineProvider=\"bounds\"

The elevation is not working properly, then you can try to tinker with phone\'s color settings.



回答13:

I believe your issue stems from the fact that you have applied the elevation element to a relative layout that fills its parent. Its parent clips all child views within its own drawing canvas (and is the view that handles the child\'s shadow). You can fix this by applying an elevation property to the topmost RelativeLayout in your view xml (the root tag).



回答14:

In my case fonts were the problem.

1) Without fontFamily I needed to set android:background to some value.

<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) with fontFamily I had to add android:outlineProvider=\"bounds\" setting:

<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\" />


回答15:

I had some luck with setting clipChildren=\"false\" on the parent layout.



回答16:

I spent some time working on it and finally realized that when the background is dark, shadow is not visible