Styling the popup menu in Android 5.0 - android

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.

Related

Android TimePickerDialog styling guide/docs?

I'm trying to style a TimePickerDialog for sdk 21+ (Lollipop). So far I've figured out how to change the default colorscheme in XML:
<style name="TimePickerTheme" parent="#style/Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">#ff2d6073</item> <!-- no effect -->
<item name="colorPrimaryDark">#ff2d6073</item> <!-- no effect -->
<item name="colorAccent">#ff2d6073</item>
<item name="android:textColor">#ffD0D102</item>
<item name="android:textColorPrimary">#ffD0D102</item>
</style>
This works but I'm looking for a guide or documentation for all the properties I can change.
AccentColor does the basic color scheme
TextColorPrimary does the text color
But what property, for example, do I need to change the big text in the 'header' of the dialog (where the current selected time is displayed)?
Is there some documentation that lists all the possible things you can change?
After digging through the AOSP theme and style xml files and a lot of googling I made some progress. I am now able to style most(!) things.
So this is a partial answer, not all the way there yet. But here's how far I got:
You can see that I'm now able to theme the header, the un(!)selected time part (minutes in this case), the circle, the numbers in that circle and the 'hand' (or selector). Oh, and the buttons are styled, too.
Let me explain how I got things working, first: the important thing is that you can't override things directly from you app's theme OR from a (alert)dialog theme/style. You have to go from one to the next, so to speak.
Example:
AndroidManifest.xml: Set custom theme for app and/or activity
<activity>
android:theme="#style/Theme.MyTheme"
</activity>
values-v21/styles.xml: (where your custom theme resides): set the timePickerDialogTheme
<style name="Theme.MyTheme" parent="#style/Theme.AppCompat.Light">
<item name="android:timePickerDialogTheme">#style/TimePickerDialogTheme</item>
</style>
Then below that, define the timePickerDialogTheme and set the timePickerStyle:
<style name="TimePickerDialogTheme" parent="#style/Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#ff2d6073</item> <!-- colorAccent here seems to work just fine? -->
<item name="android:timePickerStyle">#style/TimePickerDialogStyle</item>
</style>
Now you can define most of the styling here..
<style name="TimePickerDialogStyle" parent="#android:style/Widget.Material.Light.TimePicker">
<item name="colorAccent">#ff2d6073</item> <!-- colorAccent here seems to work just fine? -->
<item name="android:timePickerMode">clock</item>
<item name="android:headerBackground">#ff2d6073</item>
<item name="android:headerTimeTextAppearance">#style/TextAppearance.TimePickerDialogStyle.TimeLabel</item> <!-- TimePicker Time *TextAppearance* -->
<item name="android:numbersTextColor">#ff000000</item>
<item name="android:numbersSelectorColor">#ff2d6073</item>
<item name="android:numbersBackgroundColor">#ffdddddd</item>
</style>
The important line in the above is:
<item name="android:headerTimeTextAppearance">#style/TextAppearance.TimePickerDialogStyle.TimeLabel</item>
Because if you want to style the text (well, time, actually) in the header you need to define the headerTimeTextAppearance:
<style name="TextAppearance.TimePickerDialogStyle.TimeLabel" parent="#android:style/TextAppearance.Material">
<item name="android:textSize">60sp</item> <!-- from -->
<item name="android:textColor">#ffD0D102</item>
</style>
Now, if you take a look at the Widget.Material.TimePicker in AOSP styles.xml (ctrl-f 'timepicker' until you find it) you'll notice a bunch of other properties that you should be able to modify:
headerTimeTextAppearance
headerAmPmTextAppearance
headerSelectedTextColor
headerBackground
numbersTextColor
numbersBackgroundColor
amPmTextColor
amPmBackgroundColor
amPmSelectedBackgroundColor
numbersSelectorColor
Most of these work (as long as you prepend 'android:' for each of them) BUT I could not get 'headerSelectedTextColor' to work. I got a compile error saying something like "could not match property bla bla". Also, if you look at my example above, I hardcoded the textSize for the 'headerTimeTextAppearance' property because the '#dimen/timepicker_ampm_label_size' value threw errors.
In short: most of the things are listed above and how to get them working. But not all is clear. So I'd still see that complete documentation/guide :)
Android TimePicker material style with custom colors below, you can see http://www.zoftino.com/android-timepicker-example for TimePicker usage and styles.
<style name="MyAppThemeFour" parent="Theme.AppCompat.Light">
<item name="android:timePickerDialogTheme">#style/MyTimePickerDialogStyle</item>
</style>
<style name="MyTimePickerDialogStyle" parent="#style/ThemeOverlay.AppCompat.Dialog.Alert">
<item name="showTitle">false</item>
<item name="colorControlActivated">#ffd600</item>
<item name="colorAccent">#b71c1c</item>
<item name="android:textColorPrimary">#43a047</item>
<item name="android:textColorSecondary">#f44336</item>
</style>
When using version 1.5.0 of the Material Design Library for Android, I've found that I can get most of the theming with using this particular style:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyTimePickerTheme" parent="ThemeOverlay.MaterialComponents.TimePicker">
<item name="android:textColor">#FF121212</item>
<item name="android:textColorPrimary">#FF121212</item>
<item name="android:textColorSecondary">#FFF9F9F9</item>
<item name="colorAccent">#FF121212</item>
<item name="colorControlNormal">#FF121212</item>
<item name="colorPrimary">#FF121212</item>
<item name="colorSurface">#FFF9F9F9</item>
</style>
</resources>
This will yield in a generic - non colored - Dialog which works for white theme. For dark theme, simply invert the colors.
I've also asked here to have dynamic theming supported for this component.
Example screenshot using the above style:

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 menu background black with Theme.AppCompat?

For some reason in my application, when using "Theme.AppCompat" as my style, it makes my Menus black text (which I set since I want black text) on a dark grey background, as shown here:
I have tried manually setting the menu's background color using a few online resources but none seem to be working. Does anyone know what might be causing the issue? Below is my style.xml, and as you can see, the two bottom elements in the main app theme entry are me trying to change the background color using things I've found online.
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat">
<item name="windowActionBar">false</item>
<item name="android:windowBackground">#color/white_primary</item>
<item name="android:textColor">#color/text_primary</item>
<item name="android:textSize">#dimen/text_size_medium</item>
<item name="colorAccent">#color/black_primary</item>
<item name="android:popupMenuStyle">#style/PopupMenuStyle</item>
<item name="android:panelFullBackground">#drawable/menu_full_bg</item>
</style>
<style name="PopupMenuStyle" parent="Theme.AppCompat.Light">
<item name="android:popupBackground">#android:color/white</item>
</style>
<drawable name="menu_full_bg">#FFFFFF</drawable>
You can change the background color of the popup menu as below.
Create a style in your styles.xml
<style name="PopupMenuStyle" parent="Theme.AppCompat.Light">
<item name="android:background">#android:color/white</item>
</style>
Set this theme as your toolbar popup theme in your toolbar.xml
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
// Your code here
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/PopupMenuStyle" />
Hope this helps.
You can just use appNS to define the popupTheme as shown below.
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
What I did was I change my popUpTheme to DayNight so use
app:popupTheme="#style/ThemeOverlay.AppCompat.DayNight">
Refer this link
The accepted answer here worked for me. I am just repeating the same answer here again.
Add the following to your Toolbar 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:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/toolbarbackground"
android:elevation="4dp"
app:popupTheme="#style/YOUR_THEME_HERE"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
In your styles.xml:
<style name="YOUR_THEME_HERE" parent="ThemeOverlay.AppCompat.Light">
<item name="android:colorBackground">#000000</item>
<item name="android:textColor">#ffffff</item>
</style>
The above style gives white font on a black background.
Credit to #Eugen Pechanec
I discourage this line:
<item name="android:background">#android:color/white</item>
as on my device the menu popup animation behaved rather ugly. Instead it was sufficient to just use this:
<style name="PopupMenuStyle" parent="Theme.AppCompat.Light">
</style>
I tried to add this into Toolbar:
app:popupTheme="#style/Theme.AppCompat.Light"
BUT at the Night mode the background will be white, and the text white too.
(this will helpful in only Day mode, or your app does not follow Day/Night switch)
Another tried, I add this style for menu popup, as Pojaa said above:
<style name="PopupMenuStyle" parent="Theme.AppCompat.Light">
<item name="android:background">#android:color/white</item>
</style>
BUT this create an effect: when you click the menu, it show the white background of popup menu first (the white background), and then show up the items, this very not good for user experience. Maybe Android change by time, the experience will different!
You SHOULD just try this for your wish:
app:popupTheme="#style/Theme.AppCompat.DayNight"
This is late answer, but hope it will help someone else!
Not sure if this's help. It may be a simpler solution. Within AppCompat - themes_base.xml you will find the section below.
<!-- Panel attributes -->
<item name="panelMenuListWidth">#dimen/abc_panel_menu_list_width</item>
<item name="panelMenuListTheme">#style/Theme.AppCompat.CompactMenu</item>
<item name="panelBackground">#drawable/abc_menu_hardkey_panel_mtrl_mult</item>
<item name="android:panelBackground">#android:color/transparent</item>
<item name="listChoiceBackgroundIndicator">#drawable/abc_list_selector_holo_dark</item>
Create a theme within your app and apply the colour.
<style name="Theme.Base" parent="#style/Theme.AppCompat.Light.DarkActionBar">
<item name="android:panelBackground">#android:color/black</item>
</style>

Material design: Where to place elevation in android styles?

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>

Change the line color used in listSeparatorTextViewStyle

I have the following code
<TextView
android:text="#string/hello"
style="?android:attr/listSeparatorTextViewStyle" />
and I will get the following effect.
However, I am not happy with the color line. I would like to have something like
I would like it to have blue color line as in holo. I try the following custom style.
<style name="MyOwnListSeperatorTextViewStyle">
<item name="android:background">#android:drawable/list_section_divider_holo_light</item>
<item name="android:textAllCaps">true</item>
<!-- Copy from Widget.TextView.ListSeparator -->
<item name="android:background">#android:drawable/dark_header_dither</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?textColorSecondary</item>
<item name="android:textSize">14sp</item>
<item name="android:gravity">center_vertical</item>
<item name="android:paddingLeft">8dip</item>
</style>
But it won't work, as I get the following error.
error: Error: Resource is not public. (at 'android:background' with value '#android:drawable/dark_header_dither').
Have idea how can I change the line color used in listSeparatorTextViewStyle?
I needed to do this to override the typical Holo Spinner style (I didn't want the underlined item - i just wanted the arrow), and I think this can be overridden in precisely the same manner:
First off, you want to find the item you wish to override in the android styles source. There is an incredibly useful SO answer that contains all of the styles (and the names to override them) right here: Set Dialog theme to parent Theme in Android
I believe yours is the following line:
<item name="listSeparatorTextViewStyle">#android:style/Widget.Holo.Light.TextView.ListSeparator</item>
This takes us on a journey to find the style Widget.Holo.Light.TextView.ListSeparator which should live somewhere on your very own computer! But I'll make it easy and just c&p it:
<style name="Widget.Holo.Light.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
<item name="android:background">#android:drawable/list_section_divider_holo_light</item>
</style>
Now, you probably want to leave well enough alone, and just look at that background drawable. You will find it is a grey 9patch file that looks like the sinister grey line you seek to avoid.
We need to override this. I am sure there are a number of ways to do this, but I do so by customizing the theme of the application. Here is the themes.xml file:
<style name="AppTheme" parent="#android:style/Theme.Holo.Light.NoActionBar">
<item name="android:listSeparatorTextViewStyle">#style/MyOwnListSeperatorTextViewStyle</item>
</style>
<style name="MyOwnListSeperatorTextViewStyle" parent="Widget.TextView.ListSeparator">
<item name="android:background">#drawable/make_your_own_blue_9_patch_here</item>
</style>
Notice how we used the listSeparatorTextViewStyle from that previous SO post? And the parent of the custom style is the Widget.TextView.ListSeparator from android's style source? All very important.
Now you just need to apply this theme to your app, but I am assuming you have a theme already. If you haven't already, you will need to make your own 9patch but I would just look at the list_section_divider_holo_light.9.png file on your computer, and make the grey parts blue, and then make a copy and place it into your own drawables folder.
Hope this works and is helpful!

Categories

Resources