Appcompat v21 Toolbar elevation pre-lollipop

血红的双手。 提交于 2019-11-28 17:01:10

问题


First off, I know that this question has been asked before, but it hasn't been answered before. I hope someone can give me an answer.

In my application, I use the Toolbar from Appcompat_v7 (API 21). This is my code:

<android.support.v7.widget.Toolbar
    style="@style/DarkActionbarStyle"
    android:id="@+id/toolBar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/actionbar_height" />

And this is the ToolBar style I use:

<style name="DarkActionbarStyle" parent="@style/Widget.AppCompat.Toolbar">
    <item name="android:background">?attr/colorPrimary</item>
    <item name="titleTextAppearance">@style/ActionBarTitle</item>
    <item name="android:elevation">2dp</item>
    <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
    <item name="theme">@style/ThemeActionBarDark</item>
</style>

<style name="ThemeActionBarDark" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="actionBarItemBackground">@drawable/btn_dark_orange</item>
    <item name="selectableItemBackground">@drawable/btn_dark_orange</item>
</style>

The problem is, that elevation doesn't work pre-lollipop. So my question is: Is it possible to have a shadow under the ToolBar on pre-lollipop devices?


回答1:


This worked for me very well:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/primary"
    card_view:cardElevation="4dp"
    card_view:cardCornerRadius="0dp">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/primary"
        android:minHeight="?attr/actionBarSize" />

</android.support.v7.widget.CardView>



回答2:


Using CardView container for toolbar is a bad idea.

CardView is heavy, especially for low end devices.

The best way is to put a gradient Shadow view below the toolbar. Shadow view must be a direct child to the coordinator layout. ie. The appbar which contains toolbar and shadow View must be siblings.

Add this view component to your layout.

 <View
    android:id="@+id/gradientShadow"
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:background="@drawable/toolbar_shadow"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    app:layout_collapseMode="pin"/>

The drawable toolbar_shadow.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
<gradient
    android:angle="90"
    android:endColor="#33333333"
    android:startColor="@android:color/transparent"/>
</shape>

This will solve the problems in pre-lollipop devices. But we don't want this shadow in lollipop and above devices so make visibility to gone in devices with lollipop and above.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        findViewById(R.id.gradientShadow).setVisibility(View.GONE);
}

Done.




回答3:


You can add the shadow (elevation) back by using a FrameLayout with foreground="?android:windowContentOverlay". The elevation attribute is not supported pre-Lollipop. So if you are using FrameLayout like fragment container just add foreground attribute to it.




回答4:


As I've had issues with the CardView widget method, I've used the FrameLayout method as mentioned by @Sniper; it is working perfectly!

I just wanted to share the code snippet you'll have to use. Just put this directly under the toolbar where your main content starts:

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foreground="?android:windowContentOverlay">

And don't forget to close with:

</FrameLayout>



回答5:


It's possible to have real shadows - animated and generated. The method used by Lollipop is available since Froyo. Hardware acceleration used for shadow generation is available since Honeycomb I guess. Here's how it works:

  • draw your view to an off-screen bitmap with LightingColorFilter set to 0,0
  • blur the black shape (the off-screen bitmap) using the ScriptIntrinsicBlur class and elevation value as radius
  • draw the bitmap beneath the view

It requires adding custom elevation attributes, custom views capable of rendering shadows, and using render script and the compatibility library (for older devices). I'm not going to dive into the details, because there's a lot of them including issues with compilation and minor performance optimisations. But it's possible.

Why there's no shadows in the official support library?

  • it would require changes in the UI framework as it's impossible to freely draw outside view bounds
  • smooth animation requires a quite good GPU

See:

  • https://www.youtube.com/watch?v=jbU4SXblO5s
  • https://androidreclib.wordpress.com/2014/11/25/lollipops-shadows-on-gingerbread/
  • https://github.com/ZieIony/Carbon



回答6:


I'm using this answer:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/orange"
    android:titleTextAppearance="@color/White"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

    <View
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:background="@drawable/toolbar_shadow" />
</LinearLayout>

toolbar_shadow.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#3f3f3f"
        android:endColor="@android:color/transparent"
        android:angle="270" />
</shape>



回答7:


You can't use the elevation attribute before API 21 (Android Lollipop). You can however add the shadow programmatically, for example using a custom view placed below the Toolbar.

For example:

<ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/toolbar"
        android:background="@drawable/shadow"/>

Where the shadow is a drawable with a black gradient.




回答8:


To show shadow under your toolbar please use AppBarLayout available in Google Android Design Support Library. Here is an example of how it should be used.

<android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
   <android.support.v7.widget.Toolbar
            android:layout_height="?attr/actionBarSize"
            android:layout_width="match_parent"/>
     </android.support.design.widget.AppBarLayout>

To use Google Android Design Support Library enter following into your build.gradle file:

 compile 'com.android.support:design:22.2.0'



回答9:


The solution with a view to add a shadow manually would work as long as there are no action bar menus. If so, the shadow view would stop before the action bar icons.

i think it is easier to have a vertical linear layout with appbar on the top and a view for shadow below it as the next linear layout item or in my case, it is

<LinearLayout Vertical> 
  <v7 toolbar/>
  <RelativeLayout>
     <View for shadow with alignParent_top= true/>
      ....
  </RelativeLayout>
</LinearLayout>

I really hope the near future appCompat would fix this.




回答10:


Another option is the following library that provides 9patch shadows like the iosched app, android-materialshadowninepatch



来源:https://stackoverflow.com/questions/26743325/appcompat-v21-toolbar-elevation-pre-lollipop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!