I want to give the user the possibility to switch the colors skin of my entire application. I mean to switch the style of some custom views of the app dynamically when the user presses a button of the screen. I know that if you call Activity.setTheme() before onCreate() method, you can change the theme of the app dynamically, but normal Views (for example, NavigationView) with custom styles applied on their xml layout, do not have setTheme or setStyle methods, so it is does not appear possible to change their style dynamically.
I think that my objective would be possible referencing colors declared in an AppTheme declared inside styles.xml file. I mean, i can have two AppThemes declared, each one with one set of colors, and then, in the custom styles declared for the custom views, reference the colors. Something like this:
<resources>
<style name="AppTheme" parent="Theme.AppCompat">
<item name="customColor">#111111</item>
</style>
<style name="AppTheme.AnotherColor" parent="Theme.AppCompat">
<item name="customColor">#222222</item>
</style>
<style name="CustomActionBar">
<!-- title text color -->
<item name="android:textColorPrimary">#styles/customColor</item>
</style>
</resources>
So, by default, the custom Color declared on my "AppTheme" will be applied by default, using color 111111. But when I change the theme of my app using setTheme(R.styles.AppTheme_AnotherColor) the color applied will be 222222. If this would be possible it would be perfect! but it is not possible or I don't know how to access to a color declared inside a style directly from another style of the same styles.xml file. I mean that #styles/customColor is not correct and I don't know how to access that color.
How can this be achieved?
Yes, it is definitely possible to add custom attributes and colors to the themes. For this you need to:
Define your custom attribute in your res/values/attrs.xml file:
<resources>
<attr name="customColor" format="color" />
</resources>
Define the attribute's value in your themes:
<style name="AppTheme" parent="Theme.AppCompat">
<item name="customColor">#111111</item>
</style>
<style name="AppTheme.AnotherColor" parent="Theme.AppCompat">
<item name="customColor">#222222</item>
</style>
Use your custom attribute in your styles:
<style name="CustomActionBar">
<!-- title text color -->
<item name="android:textColorPrimary">?attr/customColor</item>
</style>
Related
I have a project where I defined all the styles in the theme (Button style, Checkbox Style, EditText style and so on) This way I don't need to apply any style or theme in the layouts where I use those views, because they are applied automatically by my AppTheme.
Now I encountered a problem. I wanted to define the Switch style inside the theme but it should use another color for the colorControlActivated and colorControlHighlight. By default it uses the colorPrimary which I defined in the theme, but what if I want to change that.
The problem can be fixed easy with a theme overlay or a style where I override the needed attributes that I mentioned above and apply that style/theme everywhere where I use the Swtch view. But I want to know if I can avoid that and define a default style for my Switch views inside the same theme where the colorControlActivated and colorControlHighlight are already defined.
I tried several things but this looked like the one that actually might work but it does not:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorControlActivated">#color/colorPrimary</item>
<item name="colorControlHighlight">#color/colorPrimary</item>
<item name="colorSwitchThumbNormal">#color/white</item>
<item name="switchStyle">#style/SwitchStyle</item>
</style>
<style name="AppTheme.GreenControlOverlay">
<item name="colorControlActivated">#color/green</item>
<item name="colorControlHighlight">#color/green</item>
</style>
the SwitchStyle looks like this
<style name="SwitchStyle" parent="Widget.AppCompat.CompoundButton.Switch">
<item name="android:theme">#style/AppTheme.GreenControlOverlay</item>
</style>
I dont know why this is not working because if I set the android:theme inside my AppTheme directly it does override the colorControl attributes, but if you override it from a style it does not work. If I apply this GreenControlOverlay on the Switch view inside of my layout it also works.
Is it even possible to do this?
If you have any questions please don't hesitate to ask. I hope I explained my problem well.
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.
I would like to know if it is possible (and how) to customize an existing theme.
What I'm looking for is how can I retrieve a certain attribute (i.e. color) and change it when the Activity starts and reapply the modified theme before setContentView().
Similar to setTheme(), but instead of using a resource id, use the modified theme.
Why not just make your own theme, setting the android:parent to the theme you want to copy, then set your own attributes? That is demonstrated in this documentation, like so:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CodeFont" parent="#android:style/TextAppearance.Medium">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style>
</resources>
In this case, the CodeFont style will be identical to the TextAppearance.Medium style, except for the items specified here. You can do the same with any theme, including the default Holo or Dark theme or whatnot.
Based on further research and Eric's comment there is not yet a possible way to modify a theme programmatically. Different themes can be applied programmatically but not modified. Once the style is set in XML, it cannot be modified.
I have an android manifest with an activity that I want to apply to styles to:
<activity android:label="#string/app_name" android:name="Language" android:theme="#android:style/Theme.NoTitleBar>
Is how it looks right now, but while keeping the NoTitleBar attribute, I would like to add this attribute as well:
android:style/Theme.Light"
But I'm just so new to Android that I can't figure it out.
Please help!
You cannot have more than one theme applied at once in your manifest.
I believe there is a theme Theme.Light.NoTitleBar that will do what you want - but I will show you below how you can easily do this yourself and customize more.
What you need to do is create a theme which has either Theme.NoTitleBar or Theme.Light as it's parent and customizes the bits you want -- in this case the easiest way is to create a theme with Theme.Light as it's parent and just hide the title bar (rather than have the Theme.NoTitleBar as the parent and then have to make everything light which is much harder!).
You can do this with the following code in your themes.xml file in the values folder:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- use the Android Light theme as the base for our own theme -->
<style name="MySuperTheme" parent="#android:style/Theme.Light">
<!-- hide the Window Title -->
<item name="android:windowNoTitle">true</item>
<!-- You could change the scrollbar, checkbox style, anything! -->
</style>
</resources>
Then use android:theme="#style/MySuperTheme" for your activity (or you could even apply it to your whole application by placing it on the application element -- if you apply a style to an individual activity and have one set for the whole application as well then the style of the individual activity will be the one shown).
Take a look at the Android themes.xml for a list of all the things you can customize in your own theme.
You can also look at all of the Android styles to see how they are done.
You'll need at least 2 styles, best inheriting from base styles, e.g. Theme.Material variants, or if you use appcompat then Theme.AppCompat variants. In each style override values such as colours, drawables etc with theme-specific values.
values/styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- original theme attributes -->
...
<item name="android:textColorPrimary">#FFFFFF</item>
</style>
<style name="AppTheme.Dark" parent="Theme.AppCompat">
<!-- alternative theme attributes -->
...
<item name="android:textColorPrimary">#000000</item>
</style>
This will be sufficient if you only use framework or appcompat attributes (e.g. colorAccent, android:textColorPrimary etc) in your layouts. But if you need your own attributes (e.g. a drawable with color that is different per theme), then you will need to define custom attributes.
values/attrs.xml
<attr name="themedMenuStoryDrawable" format="reference" />
<attr name="themedMenuCommentDrawable" format="reference" />
...
Specify theme-specific values for your custom attributes:
values/styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- original theme attributes -->
...
<item name="themedMenuStoryDrawable">#drawable/ic_subject_white_24dp</item>
<item name="themedMenuCommentDrawable">#drawable/ic_mode_comment_white_24dp</item>
</style>
<style name="AppTheme.Dark" parent="Theme.AppCompat">
<!-- alternative theme attributes -->
...
<item name="themedMenuStoryDrawable">#drawable/ic_subject_black_24dp</item>
<item name="themedMenuCommentDrawable">#drawable/ic_mode_comment_black_24dp</item>
</style>
Then refer to your custom attributes with ?attr/ prefix in layouts, menus etc:
menu/my_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#id/menu_comment"
android:icon="?attr/themedMenuCommentDrawable" />
<item android:id="#id/menu_story"
android:icon="?attr/themedMenuStoryDrawable" />
</menu>
Check out my blog post for the complete guide.
I have a TextView and I want to apply a Style which I use for all TextView elements plus another style which I only use within a specific Activity. Is there any possibility to do that?
Just a little piece of information that might add to the overall value of the question - shamelessly copied from: http://developer.android.com/guide/topics/ui/themes.html#DefiningStyles
If you want to inherit from styles that you've defined yourself, you do not have to use the parent attribute. Instead, just prefix the name of the style you want to inherit to the name of your new style, separated by a period. For example, to create a new style that inherits the CodeFont style defined above, but make the color red, you can author the new style like this:
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
Notice that there is no parent attribute in the tag, but because the name attribute begins with the CodeFont style name (which is a style that you have created), this style inherits all style properties from that style. This style then overrides the android:textColor property to make the text red. You can reference this new style as #style/CodeFont.Red.
You can continue inheriting like this as many times as you'd like, by chaining names with periods. For example, you can extend CodeFont.Red to be bigger, with:
<style name="CodeFont.Red.Big">
<item name="android:textSize">30sp</item>
</style>
A style under Android can have a parent style.
So just have MyActivityTextView define GeneralTextView as parent style, and change/add style properties.
Then you can use MyActivityTextView for some views and GeneralTextView for the others.
It's described in Defining Styles.
You can extend one style with another in your style.xml:
<style name="current_weekday_white" parent="current_day_white">
<item name="android:textColor">#FFABAB</item>
</style>
Inherit one style from another and copy elements from third.
<style name="Button.Style1" parent="android:style/Widget.Button">
<item name="android:gravity">center</item>
<item name="android:textSize">12sp</item>
<item name="android:background">#drawable/shape_button</item>
<!-- Here are attributes from third style -->
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textColor">#112233</item>
</style>