I noticed the UI color (eg Button background/text color) all changes from device to device, based on the current theme that is being used in a device.
What is the best practice to apply custom UI colors for Android app, so that I have same color scheme for my app in all Android devices. I can set text/background color on a UI item. I'm wondering if there is a single place where I can define all the colors which will override the current theme applied on the phone.
thx.
Yes, there is a single place where you can define these values for your app. See Styles and Themes in the Android docs for how it works.
A style is just a mapping of values to predefined names. If you find yourself repeating a number of common attributes in your layouts, you can factor that out into a style. For example, you might have a special button style that defines a specific background and text color.
A theme is a sort of meta-style. It can be applied to an Activity or even a whole application through your AndroidManifest.xml. Among other things it defines the default styles for widgets and values that control other parts of the look and feel for your UI.
When you're trying to blend in with the system in an otherwise custom UI for your app, you can query the current theme for values. Just like you use the # reference syntax #android:drawable/foo when referring to a system resource, you can use the syntax ?android:attr/foo when you want to use the value stored in the system theme attribute foo.
In your case, if you want to change the primary text color across your app, apply a custom theme that sets the attribute textColorPrimary. If you just want to be sure that an element of your app is using the primary text color as defined by the device your app is running on, you can set android:textColor="?android:attr/textColorPrimary". The same principles apply elsewhere as well.
If you want to see what attributes are used in the system, they are defined as part of the Android framework in this file: frameworks/base/core/res/res/values/attrs.xml. Look at the children of the XML element <declare-styleable name="Theme"> at the top. To see examples of what the system sets these to, see themes.xml in the same directory. Finally, not all of these attributes are public - non-public attributes cannot be set by an app, they're implementation details of the Android framework. See public.xml for the complete list of which attributes are available for use in apps.
Best practice is to apply a custom theme to your application, and override as much of the default properties as you need.
Almost everything can be changed, except
The Menu
Some properties of AlertDialog (these can be changed using a custom dialog)
OS provided views such as the Quick Search Bar (QSB)
If you like the look of the default SDK resources then you can find these in sdk_folder/platforms/android-9/data/res/ (replace 9 with the SDK version you want the resources from) - copy the ones you want into your App and reference those.
You can take a look at the theme the SDK uses:
themes.xml
styles.xml
Related
I'm building a material design playground that can switch between the available pre-defined themes that can apply the color, typography and shapes to all the material design components throughout the app.
Right now, the user can choose available themes from the PreferenceScreen:
I got a NEW requirement that should allow the user to enter a value (eg. set color of colorPrimary). From the input, I would like to modify the Theme directly so that it could apply the change in the app.
How can I do this? I'm thinking of giving an option to the user something like below:
Here's a link to my sample material design playground app:
https://github.com/ciscosoriano/material-design-dynamic-theming
Seems like you need something like this android-how-to-change-application-theme-programmatically
link: android-how-to-change-application-theme-programmatically
This should be easy and there are lot of tutorials out there, don't forget to checkout
Basically what you need to do is:
apply statically defined theme(in res/values) as usual before activity is launched.
Now get the user input when activity is launched
Then get the current theme attributes using appropriate api and recolourize the ui controls dynamically in the program.
restart activity with the updated theme.
Some more link: Set theme color dynamically
You should be comfortable handling the activity lifecycle to view the updated theme when set.
Assuming related to How to setup night mode drawables as expected
I'm trying to implement the new AppCompat DayNight theme in my Android app while providing a theme switch in the settings.
Scenario:
As said theme switch was used, the "settings" activity recreated itself as a result of a call to AppCompatDelegate#setDefaultNightMode and AppCompatDelegate#applyDayNight (the latter is available to AppCompatActivity through its getDelegate() method).
The text color was inverted, the background changed and the back arrow's color changed as well. So far so good.
As the user finished changing the app's theme, he would close the activity and continue using the app. What does he expect to happen? Exactly, the main activity should have changed its theme as well. How do we do this? Activity#recreate in Activity#onActivityResult.
The call to AppCompatDelegate#setDefaultNightMode triggers a change in the configuration, which, afaik, is being applied either by AppCompatDelegate#applyDayNight or as soon as another Activity resolves its theme & configuration in Activity#onCreate. The first applies for the settings activity, the second is what is happening now.
Now to the critical part: the app's resources are dispatched a configuration change, and are now being checked against their validity (resource qualification), and if that fails, they will be cleared from the cache so that new resources (in this case, drawables) are created in order to fully reflect the new theme & configuration.
Now as I've said, the back arrow in the settings activity did change its color, but this was not my own drawable, it was the default one that you get with getSupportActionBar.setDisplayHomeAsUpEnabled(true).
In the main activity however, I did use my own drawables, for menu icons and other ui elements for example. These just didn't change. I'm using vector drawables, which get their color from the fillColor attribute.
TL;DR
To make the DayNight theme work for me, I have defined theme attributes for certain colors used throughout my app, also for icons (drawables). These attributes are populated by the one unified theme I'm using, and are referring to colors from values-night or values-notnight depending on the current configuration. This is a redundant indirection, but makes for a better style, at least in my opinion, when used together with default theme attributes such as textColorPrimary etc..
But: as it turns out, it doesn't work. Going the attribute-way, those attributes, which are in the end colors, loose their quality of being resource qualified (night or notnight) and therefore pass the "validity test" performed on configuration change, even if that's not what's supposed to happen. Thus, after I have changed the night mode, I end up with the old, wrong drawables.
To fix this I could e.g. simply
replace android:fillColor="?attr/myCustomAttributeColorXEitherNightOrNot" with android:fillColor="#color/colorXEitherNightOrNot".
But is that really what this is supposed to be like? Am I missing some important attributes-principle here, or is it a bug? I'd like to hear some thoughts on this.
Its pity but suppose that using on bitwise operations with Configuration still only normal way to provide night theme. See example: https://gist.github.com/slightfoot/c508cdc8828a478572e0
My experience up until now when dealing with styles has been to create a style.xml file and create the properties I want for the style. If I want my style to be based on an existing style, I use the parent attribute. I then specify the style inside of my layout file on the controls that I want to apply the style to.
Where I am at a loss is when I want to use system styles and only update certain properties. I am wondering whether I can leave the layout files alone and not bother applying any styles to the controls. Instead, I would somehow update the property of the system style and that would update everywhere in my app where that style is already being used by default.
More specifically, I want to change the background color of the Actionbar but haven't found a way of doing it other than the way I described above.
You're probably looking for themes, which are collections of styles, applied either globally throughout the application, or for each Activity in particular. Start with this document and investigate further.
I want to produce a single app that would let the user select a theme and have this applied over the entire app.
I understand that this can be achieved by using setTheme in onCreate of each activity.
But I need this to work in a different way. I don't want to have the themes stored in theme.xml or styles.xml.
I want to have a list of themes stored on the web and be able to dynamically download a new theme and have it applied in the app. I want to be able to create new themes without having to build a new version or an updated version of the app.
Images would be easy to replace. Just download from a url and store locally to be re-used. But the actual theme of the app, the colours of buttons etc should be changed at run time from a theme.xml file which isn't part of the apk but is fetched online.
Is this possible?
It depends how much styling you want to be able to do. You currently can't set view items styles grammatically outside of using a resource. But you can control things like text color and background color. If that's all you need to change, I would recommend writing a Theme factory class for you app that you use to get each view element you need. For example a getButton() function that will return you a button with the background color and text color you need.
Im searching for an android gui-library with more components i could use in my app.
Example:
A microcontroller sends the rpm of a motor (via bluetooth) to my smartphone.
And i want to use my smartphone in order to show the received rpm in progressbar-like element.
But the normal progressbar looks ugly, and i would have to progressbar.setClickable(false); .
As i said before
Im searching a library with more gui-elements(optional: i could modify, customize the outward appearance on my own)
Do anybody of you know about such a library ?
Thanks so far.
If you're just concerned about the external appearance of your GUI elements, I don't think there's any support for different UI elements than the ones provided. However, have you looked into a universal Theme and style for your application?
Here are some excerpts from that document:
A style is a collection of properties that specify the look and format
for a View or window. A style can specify properties such as height,
padding, font color, font size, background color, and much more. A
style is defined in an XML resource that is separate from the XML that
specifies the layout.
A theme is a style applied to an entire Activity or application,
rather than an individual View (as in the example above). When a style
is applied as a theme, every View in the Activity or application will
apply each style property that it supports. For example, you can apply
the same CodeFont style as a theme for an Activity and then all text
inside that Activity will have green monospace font.
Here are some resources which talk about themes:
Mobile Orchard Article
Android Engineer Article
Let me know if that's what you wanted. Themes give you almost infinite possibilities to modify outwards appearance.