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