I'm updating my app with the new Toolbar from the support library v21. My problem is that the toolbar does not cast any shadow if I don't set the "elevation" attribute. Is that the normal behavior or I'm doing something wrong?
My code is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/my_awesome_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<FrameLayout
android:id="#+id/FrameLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent">
.
.
.
And in my Activity - OnCreate method:
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
I ended up setting my own drop shadow for the toolbar, thought it might helpful for anyone looking for it:
<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:layout_gravity="top"
android:orientation="vertical">
<android.support.v7.widget.Toolbar android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_alizarin"
android:titleTextAppearance="#color/White"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- **** Place Your Content Here **** -->
<View android:layout_width="match_parent"
android:layout_height="5dp"
android:background="#drawable/toolbar_dropshadow"/>
</FrameLayout>
</LinearLayout>
#drawable/toolbar_dropshadow:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#android:color/transparent"
android:endColor="#88333333"
android:angle="90"/>
</shape>
#color/color_alizarin
<color name="color_alizarin">#e74c3c</color>
Google released the Design Support library a few weeks ago and there is a nifty solution for this problem in this library.
Add the Design Support library as a dependency in build.gradle :
compile 'com.android.support:design:22.2.0'
Add AppBarLayout supplied by the library as a wrapper around your Toolbar layout to generate a drop shadow.
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
.../>
</android.support.design.widget.AppBarLayout>
Here is the result :
There are lots of other tricks with the design support library.
http://inthecheesefactory.com/blog/android-design-support-library-codelab/en
http://android-developers.blogspot.in/2015/05/android-design-support-library.html
AndroidX
As above but with dependency:
implementation 'com.google.android.material:material:1.0.0'
and com.google.android.material.appbar.AppBarLayout
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.
#layout/toolbar
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/blue"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.ActionBar" />
<View
android:id="#+id/toolbar_shadow"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#drawable/toolbar_dropshadow" />
#drawable/toolbar_dropshadow
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient
android:startColor="#android:color/transparent"
android:endColor="#88333333"
android:angle="90"/> </shape>
in your activity layout
<include layout="#layout/toolbar" />
Use /values folders to apply the correct shadow style based on OS version.
For under 5.0 devices, use /values/styles.xml to add windowContentOverlay to the body of your activity:
<style name="MyViewArea">
<item name="android:foreground">?android:windowContentOverlay</item>
</style>
<style name="MyToolbar">
<item name="android:background">?attr/colorPrimary</item>
</style>
Then add your own custom shadow by changing your Theme to include:
<item name="android:windowContentOverlay">#drawable/bottom_shadow</item>
You can grab Google's IO app shadow resource here: https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png
For 5.0 devices & later, use /values-v21/styles.xml to add elevation to your toolbar using a custom header style:
<style name="MyViewArea">
</style>
<style name="MyToolbar">
<item name="android:background">?attr/colorPrimary</item>
<item name="android:elevation">4dp</item>
</style>
Note that in the second case, I had to create an empty MyViewArea style so the windowContentOverlay wouldn't show up too.
[Update: changed resource names and added Google shadow.]
If you are seting the ToolBar as ActionBar then just call:
getSupportActionBar().setElevation(YOUR_ELEVATION);
Note: This must be called after setSupportActionBar(toolbar);
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>
i added
<android.support.v7.widget.Toolbar
...
android:translationZ="5dp"/>
in toolbar description and it works for me.
Using 5.0+
My problem is that the toolbar does not cast any shadow if I don't set the "elevation" attribute. Is that the normal behavior or I'm doing something wrong?
That's the normal behavior. Also see the FAQ at the end of this post.
Was toying with this for hours, here's what worked for me.
Remove all the elevation attributes from the appBarLayout and Toolbar widgets (including styles.xml if you are applying any styling).
Now inside activity,apply the elvation on your actionBar:
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setElevation(3.0f);
This should work.
All you need is a android:margin_bottom equal to the android:elevation value. No AppBarLayout, clipToPadding, etc. required.
Example:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginBottom="4dp"
android:background="#android:color/white"
android:elevation="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Inner layout goes here-->
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
You can also make it work with RelativeLayout. This reduces layout nesting a little bit ;)
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar" />
<View
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_below="#id/toolbar"
android:background="#drawable/toolbar_shadow" />
</RelativeLayout>
In my situation elevation doesn't work well because I haven't given any background to the toolbar. Try giving background color to the toolbar then set elevation and it will work well.
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:elevation="4dp">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:buttonGravity="center_vertical" />
</androidx.cardview.widget.CardView>
Most solutions work fine here. Would like to show another, similar alternative :
gradle:
implementation 'androidx.appcompat:appcompat:1.0.0-rc02'
implementation 'com.google.android.material:material:1.0.0-rc02'
implementation 'androidx.core:core-ktx:1.0.0-rc02'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
You layout can have a Toolbar View, and a shadow for it, below, similar to this (need modification of course) :
<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="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:titleTextAppearance="#style/Base.TextAppearance.Widget.AppCompat.Toolbar.Title"/>
<include
layout="#layout/toolbar_action_bar_shadow"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
res/drawable-v21/toolbar_action_bar_shadow.xml
<androidx.appcompat.widget.AppCompatImageView
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content" android:src="#drawable/msl__action_bar_shadow"/>
res/drawable/toolbar_action_bar_shadow.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:foreground="?android:windowContentOverlay" tools:ignore="UnusedAttribute"/>
res/drawable/msl__action_bar_shadow.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape
android:dither="true"
android:shape="rectangle" >
<gradient
android:angle="270"
android:endColor="#00000000"
android:startColor="#33000000" />
<size android:height="10dp" />
</shape>
</item>
</layer-list>
styles.xml
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
</resources>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar as Toolbar)
}
}
Full sample here, as I've noticed the IDE has a bug of saying foreground attribute is too new to be used here.
The correct answer will be to add
android:backgroundTint="#ff00ff"
to the tool bar
with
android:background="#android:color/white"
If you use other color then white for the background it will remove the shadow.
Nice one Google!
For 5.0 + : You can use AppBarLayout with Toolbar. AppBarLayout has "elevation" attribure.
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:elevation="4dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/toolbar" />
</android.support.design.widget.AppBarLayout>
actionbar_background.xml
<item>
<shape>
<solid android:color="#color/black" />
<corners android:radius="2dp" />
<gradient
android:startColor="#color/black"
android:centerColor="#color/black"
android:endColor="#color/white"
android:angle="270" />
</shape>
</item>
<item android:bottom="3dp" >
<shape>
<solid android:color="#ffffff" />
<corners android:radius="1dp" />
</shape>
</item>
</layer-list>
add to actionbar_style background
<style name="Theme.ActionBar" parent="style/Widget.AppCompat.Light.ActionBar.Solid">
<item name="background">#drawable/actionbar_background</item>
<item name="android:elevation">0dp</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:layout_marginBottom">5dp</item>
name="displayOptions">useLogo|showHome|showTitle|showCustom
add to Basetheme
<style name="BaseTheme" parent="Theme.AppCompat.Light">
<item name="android:homeAsUpIndicator">#drawable/home_back</item>
<item name="actionBarStyle">#style/Theme.ActionBar</item>
</style>
I had similar problem with the shadow. The shadow is drawn by direct parent of AppBarLayout in my case. If height of the parent is the same as AppBarLayout's the shadow cannot be drawn. So checking size of the parent layout and maybe layout remake can solve the problem. https://www.reddit.com/r/androiddev/comments/6xddb0/having_a_toolbar_as_a_fragment_the_shadow/
I am posting this because this took me hours to find so i hope it may help someone.
I had a problem that the shadow/elevation was not showing though i created a simple activity and placed the toolbar as follows:
<androidx.appcompat.widget.Toolbar
android:id="#+id/mt_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
android:background="#color/colorPrimaryDark"
android:elevation="12dp"/>
It turns out that in the manifest
setting android:hardwareAccelerated="false" was causing it! once i removed it, the shadow appeared
Just put background
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:elevation="8dp"
android:background="#fff"
android:layout_height="?android:attr/actionBarSize"></androidx.appcompat.widget.Toolbar>
You need to use background color and elevation togather.
<com.google.android.material.appbar.MaterialToolbar
app:elevation="8dp"
android:elevation="8dp"
android:background="#color/white"/>
Related
I'm struggling to make toolbar shadow appear on Android 28+. I tried multiple solutions suggested, but none worked. Following styles work well for all devices below 28:
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
style="#style/Widget.App.Toolbar"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:layout_height="?attr/actionBarSize"
/>
styles.xml
<style name="Widget.App.Toolbar.V1" parent="Widget.AppCompat.Toolbar">
<item name="android:layout_height">?attr/actionBarSize</item>
<item name="android:layout_width">match_parent</item>
<item name="android:background">?attr/colorPrimary</item>
<item name="popupTheme">#style/ThemeOverlay.AppCompat.Light</item>
<item name="android:theme">#style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>
styles.xml (v21)
<style name="Widget.App.Toolbar" parent="Widget.App.Toolbar.V1">
<item name="android:elevation">4dp</item>
</style>
I also tried to set elevation programmatically, using ViewCompat.setElevation with no success.
Does anyone has an idea how to make it work?
UPD:
I know you can create custom shadow drawable, but I would like to avoid this solution if possible. Just can't understand why such basic functionality requires additional drawable and views in layout. Also, I wonder why it works on previous Android versions. Didn't found any proofs that this behavior has changed.
I ended up setting my own drop shadow for the toolbar, thought it might helpful for anyone looking for it:
<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:layout_gravity="top"
android:orientation="vertical">
<android.support.v7.widget.Toolbar android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_alizarin"
android:titleTextAppearance="#color/White"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- **** Place Your Content Here **** -->
<View android:layout_width="match_parent"
android:layout_height="5dp"
android:background="#drawable/toolbar_dropshadow"/>
</FrameLayout>
</LinearLayout>
#drawable/toolbar_dropshadow:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#android:color/transparent"
android:endColor="#88333333"
android:angle="90"/>
</shape>
#color/color_alizarin
<color name="color_alizarin">#e74c3c</color>
I don't know why it doesn't work for many of the people, adding:
android:elevation="5dp"
Directly to the toolbar works fine for me.
I have a tabbedactivity layout, but i need to customize that layout for swipe between 2 activities, like this.
I cant change the background color, just the line indicator. Anyone knows how can i do that?
<android.support.design.widget.AppBarLayout
android:id="#+id/appbarBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.TabLayout
android:id="#+id/tabsBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
thx!
To change the background color of an item selected you'll have to use app:tabBackground
and set custom selector.
tab_selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/colorPrimaryDark" android:state_selected="true"/>
<item android:drawable="#color/colorPrimary"/>
</selector>
TabLayout:
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#drawable/tab_selector">...
I am using support Toolbar from version suppport lib 25.0.1 and randomly it shows like this:
Now this is random and I dont know how to reproduce this. Some times it shows ok some times doesnt show correctly.
This is how I use the Toolbar in my fragment:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
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="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/Theme.App.Toolbar"
android:elevation="#dimen/toolbar_elevation"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/Theme.App.Toolbar.Popup"/>
<style name="Theme.App.Toolbar">
<item name="android:textColorPrimary">#color/white</item>
<item name="actionMenuTextColor">#color/white</item>
<item name="android:textColorSecondary">#color/white</item>
<item name="android:textColorHint">#color/white</item>
</style>
Fragment:
toolbar.setTitle("Story title");
appCompatActivity().setSupportActionBar(toolbar);
As it can be seen from the screeenshot somehow the toolbar tries to put the subtitle but I dont have one.
Is this happening to other people, is this a known bug for this problem, any solution for this.
Try to use it like:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/tb_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:theme="#style/Theme.MyTheme"
tools:ignore="NewApi">
<TextView
android:id="#+id/tv_title_toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#android:color/white"
android:textSize="18sp"
/>
</android.support.v7.widget.Toolbar>
Here you can set title gravity to left.
Then access it in the code like this way:
toolbar = (Toolbar) findViewById(R.id.tb_toolbar);
tvToolbarTitle = (TextView) toolbar.findViewById(R.id.tv_title_toolbar);
tvToolbarTitle.setText(title);
The only solution for me until now is to use support library version 25.0.0
Other solutions or updates are welcomed
In our previous holo designed app (targetSdkVersion 21, with theme Theme.Sherlock.Light.DarkActionBar), we are using system style attribute attr/actionButtonStyle to define our custom action bar button style.
actionbar_custom_view_done_discard.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<include layout="#layout/actionbar_discard_button" />
<View
android:layout_width="1px"
android:layout_height="match_parent"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:background="?attr/actionBarCustomViewDividerColor" />
<include layout="#layout/actionbar_done_button" />
</LinearLayout>
actionbar_done_button.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?attr/actionButtonStyle"
android:id="#+id/actionbar_done"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView style="?attr/actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="20dp"
android:drawableLeft="?attr/actionBarDoneIcon"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="#string/save" />
</FrameLayout>
StockAlertFragmentActivity.java
public class StockAlertFragmentActivity extends SherlockFragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate a "Done/Discard" custom action bar view.
LayoutInflater inflater = (LayoutInflater) this.getSupportActionBar().getThemedContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
final View customActionBarView = inflater.inflate(
R.layout.actionbar_custom_view_done_discard, null);
The outcome is as following, when we tap on the SAVE button.
However, after migrating our app to material designed app (targetSdkVersion 23, theme Theme.AppCompat.Light.NoActionBar), system attribute attr/actionButtonStyle no longer work well with rectangle button.
Instead, it draws a round overlay on the top of rectangle button.
toolbar_with_save_discard.xml
<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_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:contentInsetLeft="0dp"
android:contentInsetStart="0dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:contentInsetRight="0dp"
android:contentInsetEnd="0dp"
app:contentInsetRight="0dp"
app:contentInsetEnd="0dp"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" >
<!-- android:elevation="4dp" is used due to http://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-elevation-android- -->
<LinearLayout
android:id="#+id/buttons_linear_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:orientation="horizontal">
<include layout="#layout/toolbar_discard_button" />
<View
android:layout_width="1px"
android:layout_height="match_parent"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:background="?attr/toolbarCustomViewDividerColor" />
<include layout="#layout/toolbar_save_button" />
</LinearLayout>
</android.support.v7.widget.Toolbar>
toolbar_save_button.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?attr/actionButtonStyle"
android:id="#+id/toolbar_save"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView style="?attr/actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="20dp"
android:drawableLeft="?attr/toolbarDoneIcon"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="#string/save" />
</FrameLayout>
I like to have the overlay drawn on the entire rectangle SAVE button.
I think most probably I can solve this, by avoiding from using style="?attr/actionButtonStyle", and supplying my very own defined selector.
However, I prefer not to do so. I prefer to use system provided style, for less maintenance headache.
How can I make style="?attr/actionButtonStyle" workable for rectangle toolbar button?
Or, Is there any other system style attribute, which will work well with rectangle toolbar button? At the same time, having ripple effect.
Attribute at play here is: actionButtonStyle which you set on your wrapping FrameLayout. On v23, it points to:
<style name="Widget.Material.ActionButton">
<item name="background">?attr/actionBarItemBackground</item>
<item name="paddingStart">12dp</item>
<item name="paddingEnd">12dp</item>
<item name="minWidth">#dimen/action_button_min_width_material</item>
<item name="minHeight">#dimen/action_button_min_height_material</item>
<item name="gravity">center</item>
<item name="scaleType">center</item>
<item name="maxLines">2</item>
</style>
The background is set to actionBarItemBackground which in turn points to this RippleDrawable:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight"
android:radius="20dp" />
The radius value is what you don't want.
To fix this, override actionBarItemBackground under your app's theme:
<style name="AppTheme" parent="....">
....
<item name="actionBarItemBackground">#drawable/custom_action_bar_item_bg</item>
<item name="android:actionBarItemBackground">#drawable/custom_action_bar_item_bg</item>
</style>
The drawable custom_action_bar_item_bg would be defined as:
res/drawable/custom_action_bar_item_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<color android:color="#...."/>
</item>
<item>
<color android:color="#android:color/transparent"/>
</item>
</selector>
res/drawable-v21/custom_action_bar_item_bg.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:id="#id/mask">
<color android:color="#android:color/white" />
</item>
</ripple>
The mask is what will give you the rectangle in case of API version > 21.
The downside: all items that use actionBarItemBackground will be affected (unless if that's okay). To fix this, you can create a separate theme to set on your FrameLayout wrapper. For example, this is your app's main theme:
<style name="AppTheme" parent="....">
....
....
</style>
Create another theme that inherits from AppTheme:
<style name="SelectiveActionBarButtonTheme" parent="AppTheme">
<item name="actionBarItemBackground">#drawable/custom_action_bar_item_bg</item>
<item name="android:actionBarItemBackground">#drawable/custom_action_bar_item_bg</item>
</style>
To use this, override android:theme on your wrapper FrameLayout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?attr/actionButtonStyle"
android:id="#+id/toolbar_save"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:theme="#style/SelectiveActionBarButtonTheme">
....
....
</FrameLayout>
And of course, the simplest approach would be to set FrameLayout's android:background to ?attr/selectableItemBackground, and be done with it.
I add the new material design actionbar from the new appcompat and I use the new toolbar widget. I set a custom background on the toolbar on xml but my problem is that the drop shadow from the actionbar is not displayed. Do you know how to do this?
Toolbar code
<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/my_awesome_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="#drawable/ab_background_textured"
app:theme="#style/MyTheme"
app:popupTheme="#style/MyTheme.Popup"/>
MyTheme style
<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:textColorPrimary">#color/abc_primary_text_material_dark</item>
<item name="actionMenuTextColor">#color/abc_primary_text_material_dark</item>
<item name="android:textColorSecondary">#ffff8800</item>
</style>
MyTheme.Popup style
<style name="MyTheme.Popup" parent="ThemeOverlay.AppCompat.Dark">
<item name="android:textColor">#ffffff</item>
</style>
Update
Like #Justin Powell suggested I add the actionBarStyle on my theme but still there is no drop shadow.
MyTheme style(Updated)
<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:textColorPrimary">#color/abc_primary_text_material_dark</item>
<item name="actionMenuTextColor">#color/abc_primary_text_material_dark</item>
<item name="android:textColorSecondary">#ffff8800</item>
<item name="android:actionBarStyle">#style/Widget.AppCompat.Light.ActionBar.Solid.Inverse</item>
</style>
I found the solution in the Google IO app to be acceptable for myself, but saw no blog or Stackoverflow post fully explaining it. What you can do is grab their Apache 2 licensed drawer shadow asset from https://github.com/google/iosched/blob/36d88985ff6813fa9035530cd426393720a6f7b4/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png and then in the layout of your Activity:
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<include android:id="#+id/toolbar"
layout="#layout/toolbar"/>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar"
android:foreground="#drawable/header_shadow">
<!-- YOUR STUFF HERE -->
</FrameLayout>
</RelativeLayout>
Whereas header shadow is
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="header_shadow" type="drawable">#drawable/bottom_shadow</item>
</resources>
for API levels <21. Just like https://github.com/google/iosched/blob/8c798c58e592b8a25111610e216c7f3ee74c3a42/android/src/main/res/values/refs.xml and https://github.com/google/iosched/blob/8c798c58e592b8a25111610e216c7f3ee74c3a42/android/src/main/res/values-v21/refs.xml.
And to be elaborate, here is toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:theme="#style/ToolbarTheme"
app:popupTheme="#style/AppTheme"/>
For pre-5.0 layouts, you can add the shadow back to the content below the toolbar by adding foreground="?android:windowContentOverlay" to the content's FrameLayout.
For example:
<?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="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.ActionBar" />
<FrameLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:windowContentOverlay"
/>
</LinearLayout>
This is how I display the shadow:
<!-- API level 21 and above then the elevation attribute is enough. For some reason it can't be set directly on the include so I wrap it in a FrameLayout -->
<FrameLayout
android:id="#+id/topwrapper"
android:background="#color/theme_primary"
android:elevation="4dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="#layout/toolbar_actionbar" />
</FrameLayout>
<FrameLayout
android:layout_below="#id/topwrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- This topshadow is hidden in code for API level 21 and above -->
<include layout="#layout/topshadow" />
</FrameLayout>
And then the topshadow layout looks like this (adjust the 5dp to get the shadow height you want):
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="5dp"
android:id="#+id/shadow_prelollipop"
android:background="#drawable/background_shadow" />
background_shadow.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#02444444"
android:endColor="#33111111"
android:angle="90"></gradient>
</shape>
toolbar_actionbar.xml
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myapp="http://schemas.android.com/apk/res-auto"
myapp:theme="#style/ActionBarThemeOverlay"
myapp:popupTheme="#style/ActionBarPopupThemeOverlay"
android:id="#+id/toolbar_actionbar"
android:background="#color/theme_primary"
myapp:titleTextAppearance="#style/ActionBar.TitleText"
myapp:contentInsetStart="?actionBarInsetStart"
android:layout_width="match_parent"
android:layout_height="?actionBarSize" />
actionbar_background.xml
<item>
<shape>
<solid android:color="#color/black" />
<corners android:radius="2dp" />
<gradient
android:startColor="#color/black"
android:centerColor="#color/black"
android:endColor="#color/white"
android:angle="270" />
</shape>
</item>
<item android:bottom="3dp" >
<shape>
<solid android:color="#ffffff" />
<corners android:radius="1dp" />
</shape>
</item>
</layer-list>
add to actionbar_style background
<style name="Theme.ActionBar" parent="style/Widget.AppCompat.Light.ActionBar.Solid">
<item name="background">#drawable/actionbar_background</item>
<item name="android:elevation">0dp</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:layout_marginBottom">5dp</item>
<item name="logo">#drawable/ab_logo</item>
<item name="displayOptions">useLogo|showHome|showTitle|showCustom</item>
</style>
add to Basetheme
<style name="BaseTheme" parent="Theme.AppCompat.Light">
<item name="android:homeAsUpIndicator">#drawable/home_back</item>
<item name="actionBarStyle">#style/TFKBTheme.ActionBar</item>
</style>