I updated my android app to the new material design, but I also wanted to add some shadow or elevation to the Toolbar. There seem to be some (hacky) ways of doing it via ima
I have a CollapsingToolbarLayout with Toolbar and a Toolbar-like View that moves up and down, but lays above NestedScrollView, like in https://github.com/k0shk0sh/CoordinatorLayoutExample.
I tried many variants. Sometimes a shadow scrolled above a screen with NestedScrollView, sometimes the Toolbar drew a solid shadow without transparency, sometimes the shadow was aliased. Anyway, this is my solution.
Say, you have a layout:
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout>
<android.support.design.widget.CollapsingToolbarLayout>
<android.support.v7.widget.Toolbar>
<!-- Toolbar views if needed -->
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!-- Footer Toolbar views if needed -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout>
<!-- Views -->
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<!-- Add this view. It draws a shadow and aligns top of NestedScrollView -->
<!-- Set visibility to gone or visible -->
<View
android:id="@+id/scroll_shadow"
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="@drawable/shadow"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
Add a shadow (drawable/shadow.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="#ffcccccc"
android:startColor="#00cccccc" />
</shape>
Add this method. Here scrollShadow is a view named "scroll_shadow":
private void setShadowVisibility(int visibility) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
scrollShadow.setVisibility(visibility);
}
}
Manipulate it as you wish. It will show a gradient on pre-Lollipop devices and shows a normal shadow for Android 5.0+.
A simple solution, when using CoordinatorLayout, is to anchor an ImageView with the "shadow" just below the AppBarLayout, or Toolbar. This even works with CollapsingToolbarLayout, and it's correctly rendered atop the "content":
<CoordinatorLayout>
<AppBarLayout android:id="@+id/app_bar">
<Toolbar/>
</AppBarLayout>
<include layout="@layout/app_bar_shadow"/>
<!-- your content usually goes here -->
</CoordinatorLayout>
Create a res/layout/app_bar_shadow.xml file, which will only be use on pre-Lollipop devices:
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
app:layout_anchor="@+id/app_bar"
app:layout_anchorGravity="bottom"
android:layout_gravity="bottom"
app:srcCompat="@drawable/shadow_app_bar"
/>
Create an "empty" res/layout-v21/app_bar_shadow.xml file, used for Android 5+ devices:
<merge/>
Finally, an appropriate res/drawable/shadow_app_bar.xml:
<shape>
<gradient
android:angle="90"
android:startColor="#00000000"
android:endColor="#30000000"
/>
<size android:height="@dimen/design_appbar_elevation" />
</shape>
I think the best solution is to put a gradient shadow view below the toolbar and manipulate with visibility depends on device sdk.
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/white"
android:fitsSystemWindows="true"
app:popupTheme="@style/AppTheme.PopupOverlay">
<TextView
android:id="@+id/centerTitleToolbarTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:maxLines="1"
android:textColor="@color/color_toolbar"
android:textSize="@dimen/titleToolbar" />
</android.support.v7.widget.Toolbar>
<View
android:id="@+id/shadow_view"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="4dp"
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="#c1c1c1"
android:centerColor="#e6e6e6"
android:endColor="#f1f1f1"
android:angle="270" />
</shape>
MainActivity.class
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
findViewById(R.id.shadow_view).setVisibility(View.VISIBLE);
}
use build file:
compile 'com.android.support:cardview-v7:23.1.1'
refer this link
to call in xml add:
app:cardElevation="8dp"
app:cardCornerRadius="8dp"
app:contentPadding="5dp"
Use CardView
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
app:cardCornerRadius="0dp">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
</android.support.v7.widget.CardView>
For Android 5.0 and above : AppBarLayout automatically provides/gives shadow in the layout.
You can also increase the elevation of the AppBarLayout by app:elevation="4dp".
For Pre-Lollipop : You can use the following link: https://github.com/vipulasri/Toolbar-Elevation-Pre-Lollipop
Note: Toolbar also supports elevation to it, using android:elevation="4dp"
New Update: In Appcompat v24.0.0, you can not set elevation to AppBarLayout using setElevation() and app:elevation as these are deprecated.
You have to use stateListAnimator property to set elevation now.
Note: set duration to 1ms in StateListAnimator in order to avoid delay in Elevation Drawing.
AppBarLayout elevation change is delayed on appCompat v24.0.0
appbar_always_elevated.xml in animator-v21 folder under res directory.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<objectAnimator android:propertyName="elevation"
android:valueTo="8dp"
android:valueType="floatType"
android:duration="1"/>
</item>
</selector>
In AppbarLayout :
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:fitsSystemWindows="true"
android:stateListAnimator="@animator/appbar_always_elevated"
android:theme="@style/AppTheme.AppBarOverlay">
</android.support.design.widget.AppBarLayout>