How can I have a drop shadow on my ActionBar (ActionBarSherlock)? - android

I am including my styled xml layout:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.Styled" parent="Theme.Sherlock">
<item name="actionBarStyle">#style/Widget.MyApp.ActionBar</item>
<item name="android:actionBarStyle">#style/Widget.MyApp.ActionBar</item>
</style>
<style name="Widget.MyApp.ActionBar" parent="Widget.Sherlock.Light.ActionBar">
<item name="titleTextStyle">#style/Widget.MyApp.TitleTextStyle</item>
<item name="background">#color/red</item>
<item name="android:background">#color/red</item>
<item name="windowContentOverlay">#null</item>
<item name="android:windowContentOverlay">#null</item>
</style>
<style name="Widget.MyApp.TitleTextStyle" parent="TextAppearance.Sherlock.Widget.ActionBar.Title">
<item name="android:textColor">#color/white</item>
<item name="android:textSize">21sp</item>
</style>
</resources>
Some of the search over internet suggests that use windowContentOverlay set to #null. But when i use it in the style xml it doesn't change anything. Can any one help what to do?

If you want to create a shadow below the ActionBar you have to set android:windowContentOverlay parameter on the application theme (in your code you are incorrectly setting it on the ActionBar style).
In your example it would be:
<style name="Theme.Styled" parent="Theme.Sherlock">
...
<item name="android:windowContentOverlay">#drawable/my_actionbar_shadow</item>
</style>
Using #null value removes the shadow.
This one line sets the shadow on ActionBar on Android 3.0 and newer. However if you are using ActionBarSherlock, it will not work as you expect. It would create the shadow on top of the window over the ActionBarSherlock on Android devices running system older than Android 4.0 (although ActionBar is present in the api since Android 3.0, ActionBarSherlock uses custom implementation for all Android versions older than Android 4.0).
To create the shadow below ActionBarSherlock you have to set windowContentOverlay parameter on the application theme (notice the missing android:).
<style name="Theme.Styled" parent="Theme.Sherlock">
...
<item name="windowContentOverlay">#drawable/my_actionbar_shadow</item>
</style>
Again, using #null removes the shadow.
Although this line works for ActionBarSherlock, it doesn't work on android devices running Android 4.0 and newer, no shadow is created under the ActionBar on such devices. So how to combine these two parameters to get the desired shadow under both ActionBar and ActionBarSherlock?
Use resource configuration qualifiers, in your case use platform version qualifiers.
In res/values/styles.xml use the second xml code. And in res/values-v14/styles.xml use the first xml code. Therefore the ActionBarSherlock version is used by default (for versions pre Android 4.0) and ActionBar version is used for Android 4.0 and newer.
Edit:
There is a bug in Android 4.3 (API level 18), android:windowContentOverlay does not work. It should be fixed in future release. In case you need it fixed in Android 4.3, you can find workarounds linked in the bug report.

As a previous answer did say use "windowContentOverlay" in the application theme and NOT the action bar style.
<style name="Theme.Styled" parent="Theme.Sherlock">
...
<item name="windowContentOverlay">#drawable/my_actionbar_shadow</item>
</style>
If you want a realistic shadow you can find one in the
"Your Android Folder"/platforms/android-16/data/res/drawable-hdpi/
ab_solid_shadow_holo.9.png and copy it to your drawable-hdpi folder then the end result is
<style name="Theme.Styled" parent="Theme.Sherlock">
...
<item name="windowContentOverlay">#drawable/ab_solid_shadow_holo</item>
</style>

In addition, above API21(Lollipop), you will need this in code, too.
getSupportActionBar().setElevation(0);

Related

Repeating style in v19/v21

I have this in my styles.xml:
<style name="UserTheme" parent="ThemeBase">
<item name="android:editTextStyle">#style/EditTextTheme</item>
</style>
Why do I have to repeat the editTextStyle line in v19/styles.xml and v21/styles.xml.
v21/styles.xml:
<style name="UserTheme" parent="ThemeBase">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:editTextStyle">#style/EditTextTheme</item>
</style>
Is there a way to just call it in the main styles.xml and have it apply everywhere so I don't have to write it multiple times?
I couldn't find any recommended solution so I i digged into AppCompat source. The way they do it is like this.
In your styles.xml
<style name="Base.V7.Theme.YourThemeName" parent="Theme.AppCompat.Light.NoActionBar">
</style>
<style name="Base.Theme.YourThemeName" parent="Base.V7.Theme.YourThemeName" />
<style name="Theme.YourThemeName" parent="Base.Theme.YourThemeName" >
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
</style>
In your styles-v21.xml
<style name="Base.V21.Theme.YourThemeName" parent="Base.V7.Theme.YourThemeName">
<item name="android:navigationBarColor">#color/white</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
<style name="Base.Theme.YourThemeName" parent="Base.V21.Theme.YourThemeName" />
In your styles-v22.xml
<style name="Base.V22.Theme.YourThemeName" parent="Base.V21.Theme.YourThemeName">
<item name="android:navigationBarColor">#color/black</item>
<item name="android:windowTranslucentStatus">false</item>
</style>
<style name="Base.Theme.YourThemeName" parent="Base.V22.Theme.YourThemeName" />
For every new version you extend the previous base version. If you want to override any attribute for different version just put it inside Base.VXX.Theme.YourThemeName block on your new styles-vXX.xml file.
Why do I have to repeat the editTextStyle line in v19/styles.xml and
v21/styles.xml?
If you've applied some STYLE to some attribute, Android will search styles.xml file for highest api level for which file_api_level<=Android_device_api_level and searches for STYLE in it. If it finds it would apply that STYLE to view otherwise will continue searching for the STYLE in lower api level files.
e.g. - If you have four files styles.xml(default), v19/styles.xml, v21/styles.xml, v25/styles.xml and your devices is running on api level 24. Then it'll search for STYLE in v21/styles.xml first, then v19/styles.xml and finally in styles.xml(default). Only first occurrence of the STYLE will get applied. So you can't just define only extra attributes in version-specific styles.xml file.
If you don't want to repeat common attributes here is an alternate. To declare window transitions for Android 5.0 (API level 21) and higher, you need to use some new attributes. So your base theme in res/values/styles.xml could look like this:
<resources>
<!-- base set of styles that apply to all versions -->
<style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/primaryColor</item>
<item name="colorPrimaryDark">#color/primaryTextColor</item>
<item name="colorAccent">#color/secondaryColor</item>
</style>
<!-- declare the theme name that's actually applied in the manifest file -->
<style name="AppTheme" parent="BaseAppTheme" />
</resources>
Then add the version-specific styles in res/values-v21/styles.xml as follows:
<resources>
<!-- extend the base theme to add styles available only with API level 21+ -->
<style name="AppTheme" parent="BaseAppTheme">
<item name="android:windowActivityTransitions">true</item>
<item name="android:windowEnterTransition">#android:transition/slide_right</item>
<item name="android:windowExitTransition">#android:transition/slide_left</item>
</style>
Now you can apply AppTheme in your manifest file and the system selects the styles available for each system version.
Is there a way to just call it in the main styles.xml and have it
apply everywhere so I don't have to write it multiple times?
Yes, there is a way in which you can maintain only one styles.xml file.
First of all, start using AppCompat themes. They provide backward compatibility and will work for older android versions as well.
Now define all of your styles in styles.xml(default) file and if your Android Studio is showing you some warning/error for some attribute which is supported in higher level apis:
You can suppress that warning using: tools:targetApi="SupportedAndroidVersionName"
Now Android will ignore that particular attribute if it's not supported and your whole style will work perfectly for both lower and higher api levels.
Read more about Styles and Themes here.
Hope it helps :)
Newer versions of Android have additional themes available to applications, and you might want to use these while running on those platforms while still being compatible with older versions. You can accomplish this through a custom theme that uses resource selection to switch between different parent themes, based on the platform version.
Why do I have to repeat the editTextStyle line in v19/styles.xml and
v21/styles.xml?
Because if your app is running on v21, v21/styles.xml will be loaded and if running on v19, v19/styles.xml will be loaded. In case you don't have v21/styles.xml or v19/styles.xml the app will automatically use your default values/styles.xml but you wont be able to take advantage of new features provide only for v21 or v19.
For more reference you can read Supporting Different Devices and Select a theme based on platform version.

How to style Android's AppBar action text?

I need to change text size of action buttons in AppBar/Toolbar. It should be 14sp, but I'll use 20sp in this example, because it is more evident. I am using appcompat-v7 22.1.1
At first I tried to use theme attribute android:actionButtonStyle:
<style name="FirstAttemptTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionButtonStyle">#style/Custom.Widget.AppCompat.Light.ActionButton</item>
</style>
<style name="Custom.Widget.AppCompat.Light.ActionButton" parent="Widget.AppCompat.Light.ActionButton">
<item name="android:textSize">20sp</item>
</style>
Then I ran application on the Lollipop and the result was as needed:
But then I used an emulator with lower version and my theming had no effect:
I digged a little deeper and discovered that abc_action_menu_item_layout.xml is used for action menu items and it has a line android:textAppearance="?attr/actionMenuTextAppearance"
So I tried to modify this theme attribute (I also had to add textStyle:bold):
<style name="SecondAttemptTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionMenuTextAppearance">#style/Custom.TextAppearance.AppCompat.Widget.ActionBar.Menu</item>
</style>
<style name="Custom.TextAppearance.AppCompat.Widget.ActionBar.Menu" parent="TextAppearance.AppCompat.Widget.ActionBar.Menu">
<item name="android:textSize">20sp</item>
<item name="android:textStyle">bold</item>
</style>
As in the first time, the result was as needed on Lollipop and no effect on any version below.
So, the question is: how to properly change text size for action menu item?
PS: I created a simple project on github to demostrate my issue
It appears that actionButtonStyle and actionMenuTextAppearance should be used without android: namespace.
As it can be seen in values-v21/values.xml of support library, Lollipop uses attribute from system theme (note the android: prefix), that's why my attempts worked with it:
<style name="Base.V21.Theme.AppCompat.Light" parent="Base.V7.Theme.AppCompat.Light">
...
<item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
...
</style>

Android actionbar style ignored by later devices, using appcompat v7

I am using the Action Bar support library (appcompat v7), my app is set to a minimum api of 7, and a target of 21.
I have two styles files, a base one, and one targeted at devices api 11+.
When running the app on a device running KitKat, it seems that android:actionBarStyle is ignored, leaving the action bar styled as default (#style/Widget.AppCompat.ActionBar.Solid), instead of applying the given background.
But if I remove my v11 styles/comment them out, KitKat listens to the actionBarStyle attribute set in the base styles.xml file and sets my custom background without any problems.
So my question, where am I going wrong with the v11 styles?
From what I understand, according to the android docs, you are supposed to supply the additional styles for devices running 11+ using the android: prefix, but this just doesn't seem to be working for me.
Stripped down, this is my /res/values/styles.xml file:
<style name="My.Theme" parent="#style/Theme.AppCompat">
<item name="actionBarStyle">#style/ActionBar.Solid</item>
</style>
<style name="ActionBar.Solid" parent="#style/Widget.AppCompat.ActionBar.Solid">
<item name="background">#drawable/ab_solid_</item>
</style>
and this is my /res/values-v11/styles.xml file:
<style name="My.Theme" parent="#style/Theme.AppCompat">
<item name="android:actionBarStyle">#style/ActionBar.Solid</item>
</style>
<style name="ActionBar.Solid" parent="#style/Widget.AppCompat.ActionBar.Solid">
<item name="android:background">#drawable/ab_solid_</item>
</style>
as you can see, the only difference between the two is the use of the android: prefix.
According to the official doc, with the new AppCompat-v21, you can remove all of values-v14+ Action Bar styles and use only one theme declaration, in values:
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
<!-- Set AppCompat’s actionBarStyle -->
<item name="actionBarStyle">#style/MyActionBarStyle</item>
</style>

Android: defining action bar style for a device running KitKat

I am defining action bar styles for an Android device running 4.4.2. I've tested the styles on a device running 4.3 and they work prefectly. The phone running KitKat however refuses to apply any of the rules defined by the style. I've defined the same theme in all three folders: values, values-11 and values-14.
<style name="AppTheme" parent="#style/Theme.AppCompat.Light">
<!-- Setting values in the android namespace affects API levels 14+ -->
<item name="android:actionBarStyle">#style/MyStyledActionBar</item>
</style>
<style name="MyStyledActionBar" parent="#style/Widget.AppCompat.Light.ActionBar">
<!-- Setting values in the android namespace affects API levels 14+ -->
<item name="android:background">#drawable/oc_actionbar_background</item>
<item name="android:titleTextStyle">#style/MyActionBarTitleText</item>
<item name="android:actionMenuTextAppearance">#style/MyActionBarMenuText</item>
<item name="android:actionMenuTextColor">#style/MyActionBarMenuText</item>
<item name="android:actionOverflowButtonStyle">#style/MyActionButtonOverFlow</item>
<item name="android:displayOptions">showHome</item>
</style>
<style name="MyActionBarTitleText" parent="#style/TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">#696969</item>
</style>
<style name="MyActionBarMenuText" parent="#style/TextAppearance.AppCompat.Widget.ActionBar.Menu">
<item name="android:textColor">#696969</item>
</style>
<style name="MyActionButtonOverFlow" parent="#style/Widget.AppCompat.Light.Base.ActionButton.Overflow">
<item name="android:src">#drawable/ic_action_search</item>
</style>
I've also added
android:theme="#style/AppTheme"
to the manifest application tag. But the styles are still not applied. I have however managed to change the action bar properties at runtime (changing the color), but that's not a desirable way of handling such problems.
If anyone could advise me on the matter, I would be most grateful.
To prevent these kind of issues, I like to use the following tool to generate the style for me: http://jgilfelt.github.io/android-actionbarstylegenerator/
Easy to use tool that generates the style just like I want it. Might help you too, since you avoid these issues. Just paste this in your project, and you're done.
Other tools can be found here: http://romannurik.github.io/AndroidAssetStudio/index.html

custom style action bar not working in android 4

For customizing my action bar I use code below in xml:
<style name="CustomActionbarTheme" parent="#style/Theme.AppCompat.Light">
<item name="actionBarTabStyle">#style/customTab</item>
<item name="actionBarStyle">#style/MyActionBar</item>
</style>
<style name="MyActionBar" parent="#style/Widget.AppCompat.ActionBar">
<item name="background">#drawable/title_bar</item>
</style>
<style name="customTab" parent="#style/Widget.AppCompat.ActionBar.TabView">
<item name="android:background">#drawable/tab_bg_selector</item>
</style>
I have no problem using api level 10 but when I run my code in higher api devices, action bars are in their default theme. I use support library v7 in my project.
Update: as of AppCompat version 21, all API levels now use the non-prefixed style names so there is no longer a need to add the android: namespaced attributes.
Now obsolete: If you are using the support library v7 ActionBar, you need to declare your custom styles twice, once without the android: prefix (for <v11 support - this is what you have) and once with (for >=v11 support - you need to add this) as per the Styling the Action Bar guide.

Categories

Resources