I want to set item elevation in some of my app's styles. Now elevation is only 21 and higher with no support library, so my natural inclination was to just create a styles-v21 xml and place it in there:
<style name="Widget.MyApp.Drawer" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:elevation">4dp</item>
</style>
The problem with this is any changes I make to Widget.MyApp.Drawer in the regular styles.xml file will be overwritten by this completely. What I'd want is for elevation to just be tacked on to the bottom of the list of style changes I made for the v21 version of this style listed in styles.xml.
So I took to creating base styles which the style I use in the views inherits from:
<style name="BaseListElement">
<item name="android:background">#drawable/listitem_background</item>
<item name="android:layout_height">#dimen/list_item_height</item>
</style>
<style name="BaseListElement.ListItem">
</style>
I leave the style blank in styles.xml, and in styles-v21, I add elevation and it works.
However this get's kind of tricky when I want to use some advanced styles:
<style name="BaseListElement">
<item name="android:background">#drawable/listitem_background</item>
<item name="android:layout_height">#dimen/list_item_height</item>
</style>
<style name="BaseListElement.BaseItem">
<item name="android:padding">#dimen/list_item_padding</item>
</style>
<style name="Widget.MyApp.ListItem" parent="#style/BaseListElement.BaseItem">
</style>
<style name="BaseListElement.BaseHeader">
</style>
In this case, BaseItem is just one style that inherits from BaseListElement, styles such as BaseHeader inherit from it as well. This is getting kind of ridiculous as you can see.
Am I overthinking this? The way I see it I have 3 choices here:
1) Continue as is and feel like an idiot
2) On the BaseListElement level, create a child style with some goofy name which is the point at which I apply the elevation, which would then (hopefully) trickle down to all the children. As soon as I have a difference between v21 children of the base however, this wouldn't work.
3) Just throw android:elevation into the styles.xml file (don't use a v21 file) and place an ignore flag on the element. I only have 5.0 devices here, so I can't easily test at the moment if this will cause a crash on older versions.
Any thoughts?
To accomplish something like this you could just create a BaseListElement.BaseItem in both styles.xml and syles-v21.xml the first one without the elevation and the second one with it. Then just extend Widget.MyApp.ListItem from BaseListElement.BaseItem which should get updated in v21 to use the elevation.
styles.xml
<style name="BaseListElement.BaseItem">
</style>
<style name="Widget.MyApp.ListItem" parent="#style/BaseListElement.BaseItem">
</style>
styles-v21.xml
<style name="BaseListElement.BaseItem">
<item name="android:padding">#dimen/list_item_padding</item>
</style>
Method 3 you can safely implement as follows:
<item name="android:elevation" tools:ignore="NewApi">4dp</item>
Related
I am using the AppCompat theme and I want set the minHeight attribute on my buttons:
<style name="Theme.MyTheme" parent="Theme.AppCompat">
<item name="android:buttonStyle">#style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="...?">
<item name="android:minHeight">60dp</item>
</style>
However, there is no Widget.AppCompat.Button style to set as the parent for MyButtonStyle. If I use android:Widget.Button, then all my buttons look like the old crappy style. I tried various other AppCompat themes like TextAppearance.AppCompat.Button, but they do not work.
Leaving out a parent theme for the button style also causes the button not to be styled correctly.
How can I customize the default Theme.AppCompat buttonStyle?
You can have Base.MyButtonStyle extend android:Widget.Holo.Button on API 14+ (in res/values-v14/styles.xml) and android:Widget.Material.Button on API 21+ (in res/values-v21/styles.xml. This style will change according to the device system version. Put your platform specific modifications here.
Then have MyButtonStyle extend Base.MyButtonStyle and define the android:minHeight here (in res/values/styles.xml). This will apply to all platforms.
You buttons then can use style MyButtonStyle.
This example assumes your minimum SDK is 14.
And yes, there's no appcompat-v7 button style (well, at least not yet).
EDIT
This assumes you're OK with Holo button on platforms older than Lollipop. It feels unobtrusive and if you can do without ripples, it should be just fine. If you want ripples I suggest you google for a third party lollipop button library.
To answer my own question, it appears AppCompat does not in fact support the Button widget presently:
AppCompat provides similar behaviour on earlier versions of Android
for a subset of UI widgets:
Everything provided by AppCompat’s toolbar (action modes, etc)
EditText
Spinner
CheckBox
RadioButton
Switch (use the new android.support.v7.widget.SwitchCompat)
CheckedTextView
The only workaround I see would be to recreate the Material button style from the Android source code, a task which extends outside the scope of my desire.
Custom Button Style With AppCompat +22
in your styles.xml
<style name="Button.Tinted" parent="Widget.AppCompat.Button">
<item name="colorButtonNormal">YOUR_TINT_COLOR</item>
<item name="colorControlHighlight">#color/colorAccent</item>
<item name="android:textColor">#android:color/white</item> </style>
in your layout.xml
<Button
android:id="#+id/but_next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/but_continue"
android:theme="#style/Button.Tinted" />
With new MaterialComponent it is convenient to use com.google.android.material.button.MaterialButton instead of regular Button.
But to style it, there is used the different attribute in the theme
- materialButtonStyle, with this parent theme Theme.MaterialComponents.DayNight.NoActionBar.
Then the theme should look like this:
<style name="NewAppTheme"
parent="Theme.MaterialComponents.DayNight.NoActionBar">
.......
<-- IMPORTANT if you are using com.google.android.material.button.MaterialButton to style them use this parameter
<item name="materialButtonStyle">#style/ButtonStyle</item>
</style>
And in ButtonStyle you can change button attributes like this:
<style name="ButtonStyle" parent="Widget.MaterialComponents.Button.UnelevatedButton">
<item name="android:minHeight">60dp</item>
</style>
Remove the android:
<style name="Theme.MyTheme" parent="Theme.AppCompat">
<item name="buttonStyle">#style/MyButtonStyle</item>
</style>
https://stackoverflow.com/a/32363833
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>
I'm making my app ready for Android 5.0, I'm using the latest compatibility library, here is what my style looks like.
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
</style>
</resources>
(The ActionBar color is being set programmatically.)
Now, I want the overflow/popup menu to have the dark background like it had in the holo implementation, but I can't get it to work, here is what it looks like:
I have tried setting the popupMenuStyle but it didn't work.
How can I make the popup menu darker?
Stop using the ActionBar. If you want a ToolBar to be set up like an ActionBar, follow this guide on the android-developers blog.
It actually mentions your use case at Dark Action Bar and provides this code:
<android.support.v7.widget.Toolbar
android:layout_height=”wrap_content”
android:layout_width=”match_parent”
android:minHeight=”#dimen/triple_height_toolbar”
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
Not a full answer but what I found so far:
In past versions you needed to specify a drawable (Check https://github.com/StylingAndroid/StylingActionBar code and tutorials)
Apparently, now that is a color. To modify it you need to do specify the following theme:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:actionBarPopupTheme">#style/popupNew</item>
</style>
<style name="popupNew" parent="android:ThemeOverlay.Material.Light">
<item name="android:colorBackground">#color/red</item>
</style>
</resources>
This works correctly if the theme applied to the app is just this.
If I add android:actionBarPopupTheme to my existing theme, it doesn't work. I am trying to figure out why.
Solved my problem by using this style:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
<item name="actionBarStyle">#style/AbStyle</item>
<item name="actionModeBackground">#color/actionmode_bg</item>
</style>
<style name="AbStyle" parent="Widget.AppCompat.Toolbar">
<item name="elevation">2dp</item>
<item name="displayOptions">homeAsUp|showTitle</item>
<!--showHome-->
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorAccent">#color/theme_accent_secondary</item>
<item name="actionBarStyle">#style/AbStyle</item>
</style>
I had to use Widget.AppCompat.Toolbar as the parent actionBarStyle
Add the property popupTheme to your toolbar:
<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="#color/color_primary"
app:theme="#style/Theme.AppCompat.Light"
app:popupTheme="#style/Theme.AppCompat" />
Or define a new style for your toolbar:
<style name="MyToolBarStyle" parent="Widget.AppCompat.Toolbar">
<item name="android:background">#color/green</item>
<item name="popupTheme">#style/Theme.AppCompat.Light</item>
<item name="theme">#style/Theme.AppCompat</item>
</style>
This question has already been answered for styling via XML, but I'm adding an explanation here of how to work out the solution to this and similar styling questions yourself.
First, this is the solution when using AppCompat. To your App's style.xml add actionBarPopupTheme to your theme:
<style name="Theme.MyTheme" parent="#style/Base.Theme.AppCompat.Light.DarkActionBar">
...other stuff here
<item name="actionBarPopupTheme">#style/Theme.MyTheme.ActionBarPopupTheme</item>
</style>
<style name="Theme.MyTheme.ActionBarPopupTheme" parent="#style/ThemeOverlay.AppCompat.Light">
<item name="android:textColor">#android:color/white</item>
<item name="android:background">#android:color/black</item>
</style>
Here's the steps I took to arrive at this solution (it takes a bit of detective work as the Android documentation is poor):
Open your App's style.xml in Android Studio
On the line where you App's theme is defined, put your screen cursor in the parent theme (e.g. click in #style/Base.Theme.AppCompat.Light.DarkActionBar) then press F4. This should take you to the source code for the style in the appcompat library.
Within this style I saw this line:
< item name="actionBarPopupTheme">#style/ThemeOverlay.AppCompat.Light< /item>
This looked like a possible place to change the theme of the popup. I searched for "actionBarPopupTheme" in the poor
Android developers documentation and found "Reference to a theme that should be used to
inflate popups shown by widgets in the action bar". So this was worth playing with.
I copied the appcompat line containing "actionBarPopupTheme" to my style.xml then in this line replaced the item's theme reference (the bit in bold above) with Theme.MyTheme.ActionBarPopupTheme.
In my style.xml I created my new style named Theme.MyTheme.ActionBarPopupTheme. I used the same parent that was used in the style I copied from the appcompat source (the bit in bold above).
To ensure my new popup style was working, I changed the parent style to ThemeOverlay.AppCompat.Dark then ran and tested the code on a device. The popup style changed, so now I knew my overriding of actionBarPopupTheme was the correct thing to do. Then I changed back to ThemeOverlay.AppCompat.Light.
The next challenge is to work out what item names to override in Theme.MyTheme.ActionBarPopupTheme. I changed the text and background colours. To find the correct item names that change the style of something can be tricky in some cases. One way to find less obvious style item names is to look through the style definitions in the appcompat xml file (the one you opened when pressing F4 in the 2nd step above), continually descending into parent styles (F4 again!) until you find something that may do what you want. Google searches will help here too.
This theme works fine, referencing three custom styles for the 3 parts of the ActionBar's tabs.
But the "dividerPadding" has no effect on any of them - running on API 17 devices.
<style name="Theme.AppEmptyTitleBar" parent="android:style/Theme.Holo">
<item name="android:actionBarStyle">#style/AB</item>
<item name="android:actionBarTabStyle">#style/ABT</item>
<item name="android:actionBarTabBarStyle">#style/ABTB</item>
</style>
<style name="AB" parent="android:style/Widget.Holo.ActionBar">
<item name="android:dividerPadding">20dip</item>
</style>
<style name="ABT" parent="android:style/Widget.Holo.Light.ActionBar.TabView">
<item name="android:dividerPadding">20dip</item>
</style>
<style name="ABTB" parent="android:style/Widget.Holo.ActionBar.TabBar">
<item name="android:dividerPadding">20dip</item>
</style>
First of all, the dividerPadding attribute is (as far as I know) only applicable to the *ActionBar.TabBar style.
I've tested your style using a very basic application making use of the native ActionBar and a device providing API 17. I've set the dividerPadding attribute to different values and left the rest of the attributes with default values. Here are the results:
dividerPadding="0dip":
dividerPadding="15dip":
dividerPadding="20dip":
As you can see, divider is gone on the last image. So my first advice would be to check if you see it at all. Other than that, the dividerPadding seems to be working as expected.
My second advice comes from the way Android platform handles style resources placed in different values-* directories. My hunch is that you might be making use of your action bar styles in the default values directory. If you then happen to provide an override of these styles in a values-* directory which is compatible (e.g. values-vX where X <= 17), the styles from values will be ignored. As an example, consider that you've placed these sample styles in the values/styles.xml file:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="#android:style/Theme.Holo">
<item name="android:actionBarTabBarStyle">#style/ABTB</item>
</style>
<style name="ABTB" parent="#android:style/Widget.Holo.ActionBar.TabBar">
<item name="android:dividerPadding">0dip</item>
</style>
</resources>
If you then place this style definition in values-v17/styles.xml:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="#android:style/Theme.Holo">
</style>
</resources>
it will override the AppTheme style, effectively "resetting" (technically: ignoring) the whole actionBarTabBarStyle style (including the dividerPadding attribute value). In effect, you won't see any changes made to the ABTB style.
Edit
Yup, I assumed you know that, sorry :( The dividerPadding value applies only to:
Top and bottom of divider when the TabWidget (it's the container of tab labels) draws tabs horizontally.
Left and right sides of divider when the TabWidget draws tabs vertically.
Which is exactly what you see in the screenshots. As far as I know, you have to set divider to a drawable which will force additional padding. I believe the layer drawable will be great for that purpose because you can set padding explicitly for every layer.
I'm trying to put a style in all my app, so i created a theme with my style inside :
<resources>
<style name="MyTheme" parent="android:Theme.Holo.Light">
<item name="android:textAppearance">#style/subtitle</item>
</style>
<style name="subtitle parent="#android:style/TextAppearance">
<item name="android:textColor">#color/purple</item>
<item name="android:textSize">40sp</item>
</style>
</resources>
But textAppearance doesn't work it stay the same, but when i put something like textColor in my theme, it works
This is a quite old question, but the answer may help someone.
The key to solve this is in the "precedence order of styling techniques" here:
on the top is the highest precedence, at the bottom is the lowest precedence.
As we can see theme has the lowest precedence, in your example, your android:textAppearance property is being overridden by the default style of every view that accepts this attribute, the default style property is defined in every them for every specific view that accepts this attribute, in this case android:Theme.Holo.Light provides the default style for textView as android:textViewStyle... for buttons is android:buttonStyle (which inherits its textAppearance from TextView), and so on.
So if you are trying to apply that android:textAppearance property to a TextVew you should use <item name="android:textViewStyle">#style/subtitle</item> instead of <item name="android:textAppearance">#style/subtitle</item> inside MyTheme. Away to veryfy this is setting android:textViewStyle to null, that way your current code will work fine with textViews <item name="android:textViewStyle">null</item>
This post explains this precedence a bit deeper:
https://medium.com/androiddevelopers/whats-your-text-s-appearance-f3a1729192d
What I can see is, you have not declared the color in your xml for theme. Please add the following line within the <resources> and try. Your xml will look like:
<resources>
<style name="MyTheme" parent="android:Theme.Holo.Light">
<item name="android:textAppearance">#style/subtitle</item>
</style>
<color name="purple">code for your color</color>
<style name="subtitle parent="#android:style/TextAppearance">
<item name="android:textColor">#color/purple</item>
<item name="android:textSize">40sp</item>
</style>
I think this will do.
Depends on your target API you need to put your customization code in different /res/values-vxx/style.xml files.
For TextView, try android:textAppearanceSmall inside your theme instead.