How Do I extend Android Material Dark Theme - android

I know I might be making more than enough mistakes here. But do lemme know.
I've tried going through MaterialIO documentation the best way I can, and it all looks so spun up and complicated with a dozen links in each page redirecting me to another minor component.
That's when I decided to TRY it.
I added materialIO stuff to my dependencies
I then added Material to my manifest file, and wrote this
<application ...
android:theme="#style/Theme.MaterialComponents.DayNight" >
</application>
Next, I made a values/themes.xml and values-night/themes.xml as instructed by some part of the material IO page.
My intuition was to write a style tag in those resources that extended the Material theme and set my color values. The colors I found from the materialIO page :
Background (0dp elevation surface overlay)-->
Surface (with 1dp elevation surface overlay)-->
Primary
Secondary
On background
On Surface
On Primary
On Secondary
So I started adding the tags to values-night/themes.xml. I couldn't apply android: to some tags and some tags raised errors when I did.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppCompat.." parent="Theme.MaterialComponents.DayNight">
<item name="android:colorBackground">#color/JDBG</item>
<item name="colorSurface">#color/JDSurface</item>
<item name="colorPrimary">#color/JDPrimary</item>
<item name="android:colorSecondary">#color/JDSecondary</item>
<item name="android:OnBackground">#color/JDOnBackground</item>
<item name="android:OnSurface">#color/JDOnSurface</item>
<item name="OnPrimary">#color/JDOnPrimary</item>
<item name="OnSecondary">#color/JDOnSecondary</item>
</style>
</resources>
Then I added the colors to the respective colors.xml and colors-night.xml files, which told me that those values didn't have a declaration in the base values folder and it might raise issues.
I do not want to toil at nothing with very abstract documentation that leads me on ten directions at every point. Hence the question . . .
Is there anything wrong I've done ?
What do I do next ?

Just define your theme in a resources file.
For example res/values/styles.xml:
<style name="MyTheme" parent="Theme.MaterialComponents.DayNight">
<item name="colorPrimary">#color/....</item>
<item name="colorSecondary">#color/....</item>
<item name="colorOnPrimary">#color/....</item>
<item name="colorOnSecondary">#color/....</item>
.....
</style>
Define the colors in res/values/colors.xml and res/values-night/colors.xml.
Then apply the theme in the Manifest:
<application ...
android:theme="#style/MyTheme" >
Check also the official guide.

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:

Changing themes and styles based on the Android version on build

I know I can add different XMLs for different API levels, for example having different styles for values-v21 and values-v19. What I'm trying to understand is how the build system actually works with those different values? So for example if I have the bulk of my styles common across all APIs and one item of one style changes between 21 and the rest, do I:
1) Copy the whole styles.xml into v21 and change the one value I need to change
2) Only add that one style that changed to styles.xml under v21
3) Only add that one item of that one style that changed under 21
It's confusing and I couldn't find any documentation how the built process handles merging styles.
Rules are quite clear:
While running Android selects the best-matching style
If selected style is a child style, Android merges its items with parent best-matching style
If you provide your mutable item via a reference, just define its value to match selected api version.
<style name="SomeStyle">
<item name="someColor">#color/some_color</item>
</style>
You can have some_color.xml in color-v21 folder for API 21 and a common version of this file in a color folder for all other api levels.
Example:
You want to have the following style for non-v21 API
<style name="FinalStyle">
<item name="commonText">It\'s a common text</item>
<item name="specificDrawable">#drawable/icon</item>
<item name="specificColor">#color/primary_color</item>
<item name="specificText">non-v21</item>
</style>
And the following style for v21 API
<style name="FinalStyle">
<item name="commonText">It\'s a common text</item>
<item name="specificDrawable">#drawable/icon</item>
<item name="specificColor">#color/secondary_color</item>
<item name="specificText">v21</item>
</style>
Specific-parameters differ between v21/non-v21 API, common parameters are common.
How to do it?
res/values/styles.xml
<style name="BaseStyle">
<item name="commonText">It\'s a common text</item>
<item name="specificDrawable">#drawable/icon</item>
</style>
<style name="FinalStyle" parent="BaseStyle">
<item name="specificColor">#color/primary_color</item>
<item name="specificText">non-v21</item>
</style>
res/values-v21/styles.xml
<style name="FinalStyle" parent="BaseStyle">
<item name="specificColor">#color/secondary_color</item>
<item name="specificText">v21</item>
</style>
res/drawable/icon.png
Common icon
res/drawable-v21/icon.png
v21 icon
When Android searches FinalStyle for v21, it selects FinalStyle definition from res/values-v21 as best-matching style, and merges with BaseStyle. In this example there is also another best-matching resource search, when Android searches #drawable/icon.
This is for anyone who comes across this and is still just as confused as I was, even after a lot of reading and trial & error. Hopefully this helps.
The folder structure is like #Dmitry stated.
res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppBase" parent="Theme.MaterialComponents.NoActionBar">
<!-- simple: overrides colorPrimary in parent theme -->
<item name="colorPrimary">#color/brand_blue</item>
<item name="colorSecondary">#color/brand_grey</item>
<!-- sets the attributes in materialButtonStyle with style: myMaterialButton -->
<!-- the materialButtonStyle attribute is what actually changes the button settings -->
<item name="materialButtonStyle">#style/myMaterialButton</item>
</style>
<!-- this style consists of common 'attributes' among all API versions -->
<!-- you can choose to add a parent to inherit an additional style -->
<!-- unlike the materialButtonStyle attribute, this parent is not necessary to change the button settings -->
<style name="myMaterialButton" parent="Widget.MaterialComponents.Button">
<item name="cornerRadius">60dp</item>
<item name="android:paddingVertical" tools:targetApi="26">20dp</item>
</style>
<!-- this will add on and override AppBase and should include any changes that differ from other API versions -->
<style name="AppBaseChanges" parent="AppBase">
<!-- to inherit myMaterialButton, you don't have to include it in here, since it's in AppBase -->
<!-- however, if you want to extend myMaterialButton, create a new style as its child -->
<item name="materialButtonStyle">#style/myMaterialButtonAPI_All</item>
</style>
<!-- make sure the parent is myMaterialButton to inherit/override its settings -->
<!-- this will be picked for all APIs lower than other styles like this -->
<style name="myMaterialButtonAPI_All" parent="myMaterialButton">
<item name="backgroundTint">?attr/colorPrimary</item>
</style>
</resources>
res/values-v2/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- restate the same declaration as the other xml file-->
<style name="AppBaseChanges" parent="AppBase">
<!-- use a different name (...API_2) for the overriding style -->
<item name="materialButtonStyle">#style/myMaterialButtonAPI_2</item>
</style>
<style name="myMaterialButtonAPI_2" parent="myMaterialButton">
<item name="backgroundTint">?attr/colorSecondary</item>
</style>
</resources>
Set the manifest theme to AppBaseChanges. The app will pick only one AppBaseChanges style to apply changes, so be sure to carefully override the right styles to ensure you are inheriting from lower level versions.
For some reason, AndroidStudio doesn't do a good job at all previewing themes, so before you think it's not working, relaunch the app to see the changes. There are also situations where I have no idea why it wasn't updating the setting and couldn't find where it was overriding the theme. In those cases you can dig further, or avoid the hassle and just apply the relevant style directly to the view.
Here's the order of precedence for the sample themes described above. The higher the style, the higher precedence it has and will override the lower style.
either myMaterialButtonAPI_All or myMaterialButtonAPI_2
AppBaseChanges (only one is chosen)
myMaterialButton
Widget.MaterialComponents.Button
AppBase
Theme.MaterialComponents.NoActionBar
You may maintain only one styles.xml(default) file for all the device version.
Checkout my answer to How to remove repeating of similar styles in v19/styles.xml and v21/styles.xml files
https://stackoverflow.com/a/53445541/5745574

Styling the popup menu in Android 5.0

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.

How to define a theme to correctly change text color globally?

I am trying to change text color globally in my application, so by the instructions of http://developer.android.com/guide/topics/ui/themes.html I defined two themes in a xml file and set it in the manifest file. But the result was: some text change and major don't, I tried a lot of things, did a lot of research but I wasn't successful in find a way to do this. I observed that the text that changed the color was normally in TextView's that were in first level of the layouts. I am not sure, but I think second level and, so, and the ones that were in listviews didn't change. Can anyone give me a clue? Thanks in advance.
my theme file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Dark" parent="#android:style/Theme.Black.NoTitleBar">
<item name="android:textColor">#color/green</item>
</style>
<style name="Light" parent="#android:style/Theme.Light.NoTitleBar">
<item name="android:textColor">#color/yellow</item>
</style>
</resources>
Manifest file entry:
<application
android:name=".TestApplication"
android:icon="#drawable/test"
android:label="#string/app_name"
android:theme="#style/Dark">

Android App Custom Background

I feel like this is listed somewhere and is extremely easy but I cannot seam to find a straightforward answer. How do you set a custom background image. For instance set a PNG as the default background for my app instead of the black screen. Manifest, Layout, Main code thing? An example would be extremely amazing.
xml/values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyTheme" parent="android:Theme.Light"> <!-- Or any other parent you want -->
<item name="android:windowBackground">#drawable/yourcustombackgroundimage.png</item>
</style>
</resources>
and use this style in the manifest file.
<application android:theme="#style/MyTheme">
For those of you that are still looking to do this, the correct way to do it has changed slightly. Piggy-backing off of 500865's answer, here is the adjusted code:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="MyTheme" parent="android:Theme.Holo">
<item name="android:background">#drawable/dummy_background_image</item>
</style>
</resources>
Basically, you have to change windowBackground to just background, you have to include the line about xmlns:android, and you should (although not required) remove the .png extension.

Categories

Resources