Android widget with multiple color themes - android

What is the best method to set a widget colors theme saved on SharedPreferences. Users choose their preferred colors theme and programatically I set the theme.
For example I have two styles for a TextView with id "widgetThemeDate":
<style name="widgetThemeDate" parent="#style/widgetThemeLight">
<item name="android:textColor">#color/colorWhite</item>
</style>
<style name="widgetThemeDate" parent="#style/widgetThemeDark">
<item name="android:textColor">#color/colorBlack</item>
</style>
In this case I receive the following error: "error: Resource entry widgetThemeDate already has bag item android:textColor."
How can I set "widgetThemeDate" color depending user's choice?

You can't set whole themes on a view programatically (see this discussion), but you can change certain aspects progamatically. For instance. you case you could use the setTextColor() method to change the color of text programatically on ay TextView.

Related

2 Spinner with different style in same project

Surfing the web I've found this site which generates Android custom themes. I've used it to create my personal theme: it inherits from Android:Widget.Holo (should be the dark one with white text) and some fancy widget witha a custom color.
Because the theme inherits from Android:Widget.Holo, I have dark background and white text; but in some activity i need the opposite: white background with dark text.
When it comes to change the text color of most item i can do it easily using android:textColor="#android:color/black", but when i try to use it on spinner item it does nothing.
I've tried to create a new style only for spinner items, but i canno't apply it...
This is the first style generated (white text on black background):
<style name="SpinnerAppTheme" parent="android:Widget.Holo.Spinner">
<item name="android:background">#drawable/apptheme_spinner_background_holo_dark</item>
<item name="android:dropDownSelector">#drawable/apptheme_list_selector_holo_dark</item>
</style>
And this is the second I've generated (the opposite, back text on white background):
<style name="SpinnerDarkTextAppTheme" parent="android:Widget.Holo.Light.Spinner">
<item name="android:background">#drawable/apptheme_spinner_background_holo_light</item>
<item name="android:dropDownSelector">#drawable/apptheme_list_selector_holo_light</item>
<item name="android:textColor">#android:color/black</item>
</style>
But when I use style="#style/SpinnerDarkTextAppTheme nothing happens.
How can I do to have 2 different styles (obviously working at the same time) for my spinners?
SOLVED using this piece of code.
You can create two themes in the XML and switch between them before you set the content view:
https://stackoverflow.com/a/6390025/2219600
Another approach:
https://stackoverflow.com/a/16101936/2219600

Use appropriate colors irrespective of themes

I want my activity to have two possible themes, say Theme_Holo and Theme_Holo_Light, as selected by the user. I need to programmatically draw things like horizontal dividers in this activity. The color of the divider should depend on the selected theme. How can I do that easily?
Ideally there should be a name for the standard color of a divider irrespective of the theme used, and the actual RGB realization of that color name would match the selected theme automatically. Is there such thing? It seems unlikely to me that the programmer needs to hardcode RBG values.
Of course, the divider is only an example. I would also like to name the color of EditText, or other widgets, in a way that does not depend on the theme.
In your Activity's onCreate() method(s), before calling setContentView(), set the theme using this.setTheme(customTheme);
or give it a try, Using Themes in Android Applications
You can create your own theme attributes and use them in your app's themes, and allow the user to switch between your app's themes.
First, make a file called attrs.xml in /res/values folder and define some theme attributes:
<resources>
<attr name="myDividerColor" format="color" />
</resources>
Next, make two themes in your /res/values/styles.xml (or in /res/values/themes.xml if you do your themes and styles separately). One theme extends Android's dark theme and one extends Android's light theme. Add your custom attributes to your themes:
<resources>
<!-- Dark theme -->
<style name="AppTheme_Dark" parent="#android:Theme.Holo">
...
<item name="myDividerColor">#color/divider_dark</item>
</style>
<!-- Light theme. -->
<style name="AppTheme_Light" parent="#android:Theme.Holo.Light">
...
<item name="myDividerColor">#color/divider_light</item>
</style>
</resources>
Note that I used name="myDividerColor", NOT android:name="myDividerColor"
Finally, in your Activity code you can get the color as follows:
// the attrs you want
int[] attrs = {R.attr.myDividerColor};
// get attr values for the current theme
TypedArray a = obtainStyledAttributes(attrs);
// first arg is the index of the array, in same order as attrs array above
// second arg is a default value (if not defined or not a resource)
int dividerColor = a.getColor(0, Color.TRANSPARENT);

override standard style with ABS

In my AndroidManifest file i do not declare a theme.
The result is:
black background and ABS with blue background, also states of list item's is blue.
thats fine.
now i want to make to set the indeterminateProgressStyle to Widget.ProgressBar.Small
Therefore i have to declare my own style like this:
<style name="Custom" parent="??">
<item name="android:actionBarStyle">#style/ActionBarIPS</item>
</style>
what should i enter in the parent parameter?
i want all style behaviors like before (black background with blue ABS and blue list item states etc as it is defined when i dont declare a theme attribute in AndroidManifest.
EDIT:
i also need to know this parent's value:
<style name="ActionBarIPS" parent="ABS with blue background">
<item name="android:indeterminateProgressStyle">#style/IndeterminateProgress</item>
</style>
the version without a style in manifest:
the version with custom style and parent=Theme.Sherlock
i want the first version with indeterminate spinner set to "small"
It's depend to your current style, It can be Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.ForceOverflow and etc, e.g:
<style name="Custom" parent="Theme.Sherlock or Theme.Sherlock.Light">
<item name="android:actionBarStyle">#style/ActionBarIPS</item>
<item name="android:indeterminateProgressStyle">#style/IndeterminateProgress</item>
</style>
Note: You must declare this style in style.xml in your values directory.
Edited:
You got blue ActionBar without using ABS because you're using Samsung TouchWiz default UI.
If you install your APK in non-samsung devices you won't see this blue action bar, But If you are forced to have blue actionbar then put the following image in your drawable directory and set it as your actionbar background through:
getSupportActionBar().setBackgroundDrawable(getResources()
.getDrawable(R.drawable.TouchWiz_ActionBar_Bg));
Try to use "Theme.Sherlock" as a parent. Also I suggest to add:
<item name="actionBarStyle">#style/ActionBarIPS</item>

Dynamic themes and custom styles

I've got an app with two themes (dark and light) that can be selected at runtime. This works. I also have a ListView with rows that can have one of three different layouts, each of which has a style (say, different colors). This also works. But I can't get these two features to work together. I really need six different styles, three for one theme (dark) and three for the other (light), but I can't figure out how to choose a style for a list item based on the current theme, or get that effect any other way by using XML files. My three layouts each point to a custom theme that sets the color, but that overrides whatever theme I've got set. Themes can only contain items that are "styleable", so I can't put my own custom items in there. There may be a way to do this programmatically, but I was hoping to do it declaratively. Any ideas?
Thanks to wingman for the hint. My situation involved colors, which are a bit more complicated, so I'll write up my solution here.
I have two themes (light and dark) which the user can choose from in the Settings screen. I have a ListView which can have two types of rows (plain and note), each with its own styling. Firstly each layout needs to point to a style:
<TextView style="#style/PlainItemText" ... />
(or NoteItemText) and we need to define the styles:
<style name="PlainItemText">
<item name="android:textSize">#dimen/list_item_font_size</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?plainTextColor</item>
</style>
The text color can't be fixed because it depends on the selected theme. We must create a custom attribute and refer to it with a question mark, as above. We define the attribute in res/values/attrs.xml:
<!-- Attributes we use to set the text color of the various list items. -->
<attr name="plainTextColor" format="reference|color"/>
<attr name="noteTextColor" format="reference|color"/>
We can then define the various colors. Here we have two styles and two themes, so we need four color state lists, each in its own file under res/color. For example, here's res/color/plain_text_color_dark.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:color="#android:color/white"/>
<item android:state_selected="true" android:color="#android:color/black"/>
<item android:state_focused="true" android:color="#android:color/black"/>
<item android:state_pressed="true" android:color="#android:color/black"/>
<item android:color="#android:color/white"/>
</selector>
The selected/focused/pressed colors are the same in all these files because they're over the highlight color. Be careful with the state_window_focused version. It didn't behave as advertised, and I had to set it to the default color (the last line above) in all cases. Now we need to create our themes and bind the attributes to one of the colors. These lines go into res/values/themes.xml:
<style name="Theme.Dark" parent="android:Theme">
<item name="plainTextColor">#color/plain_text_color_dark</item>
<item name="noteTextColor">#color/note_text_color_dark</item>
</style>
<style name="Theme.Light" parent="android:Theme.Light">
<item name="plainTextColor">#color/plain_text_color_light</item>
<item name="noteTextColor">#color/note_text_color_light</item>
</style>
Finally we pick a theme at run-time, in an Activity's onCreate() method, before calling super.onCreate():
if (isDarkTheme) {
activity.setTheme(R.style.Theme_Dark);
} else {
activity.setTheme(R.style.Theme_Light);
}
Note that I don't take into account newer themes like Holo, so my app looks old on Honeycomb and later. I'll fix that at some point, but it wasn't a regression here.
A twist in my case is that some Activities have a larger title bar in order to fit some buttons. In principle I should have created four themes, a light and dark for a narrow title and a light and dark for a fat title. But instead I created a mix-in style:
<!-- Mix-in style for activities. -->
<style name="ButtonTitleBar">
<item name="android:windowTitleSize">44dp</item>
</style>
and procedurally add it to whatever theme I'm using. This code goes right after the above setTheme() calls:
if (buttonTitleBar) {
// Mix in this other style.
Resources.Theme theme = activity.getTheme();
theme.applyStyle(R.style.ButtonTitleBar, true);
}
I didn't see this documented anywhere, and I don't know if it's legit, but the code of Activity.getTheme() implies that it should work fine, and it has worked in all my testing. This can help avoid the combinatorial explosion of themes that you can find in the standard Android theme list.
It's a long time ago that Lawrence Kesteloot published his solution in 2012. Now it is six years later, a am new in Android and try to solve the similar problem:
How can I exchange the whole style of the application by just exchanging one theme?
This is a generalisation of Lawrences issue how to organise two exchangeable themes.
I figured out a solution based on Lawrence's and going a step further.
(Not claiming it is the perfect solution, yet an improvement.)
Lawrence figured out the power of user defined attributes to reach this goal. He uses them to address colours depending on the the currently selected theme.
While this is working it still requires to define attributes for each and every property. It doesn't scale well. So why not bundling the properties into styles and themes and using the same mechanism?
This results in a master theme, that is defining child themes and styles.
res/values/attrs.xml
<resources>
...
<attr name="mainViewTheme" format="string"/>
<attr name="asideViewTheme" format="string"/>
...
</resources>
When defining the attribute to set a theme, there is no special format for it. The format string does it.
res/values/styles.xml
<style name="MasterTheme">
...
<item name="mainViewTheme">#style/MainViewTheme</item>
<item name="asideViewTheme">#style/AsideViewTheme</item>
...
</style>
<style name="MainTextTheme">
...
</style>
<style name="MainViewTheme">
...
</style>
res/layouts/main.xml
<TextView
android:theme="?mainViewTheme"
...
By exchanging the master theme all styles are adjusted. It still requires the definition of a handful of theme attributes and then does a powerful job. Setting up attributes for every property is not required any more.

Different formats for different Textview defined by Custom style

I have a problem figuring out how to do this:
I am currently coding an app that comes with different themes (User can select the complete appereance of the app out of a list of different styles).
Then the list item is selected I want to call setTheme(R.style.Own_App_Style0); to change the complete appearance.
The problem is best explained by an example:
Lets say we have 2 TextView.
Theme1
1. TextView: TextColor should be green and TextSize 15sp.
2. TextView: TextColor should be red and TextSize 10sp.
Theme2
1. TextView: TextColor should be blue and TextSize 10sp.
2. TextView: TextColor should be yellow and TextSize 10sp.
Of course I know that by setting <item name="textViewStyle">#android:style/Widget.TextView</item> I can change the default appearance of TextViews.
But how can it be done to have lets say two (ore more) different types of TextView with different applied styles (and by xml)?
Found a solution (basically in this answer setTextAppearance through code referencing custom attribute). In case anyone else has this problem I shortly explain:
Declare in style.xml a attribute and in the actual style definition asign a value (reference) to this attribute:
<declare-styleable name="CustomTextView">
<attr name="mainTextView" format="reference"/>
</declare-styleable>
<style name="appstyle0" parent="android:style/Theme.Holo.Light">
<item name="#attr/mainTextView">#style/CustomTextViewAppearance1</item>
<item name="android:textViewStyle">#style/CustomTextViewAppearance2</item>
</style>
<style name="appstyle1" parent="android:style/Theme.Holo.Light">
<item name="#attr/mainTextView">#style/CustomTextViewAppearance2</item>
<item name="android:textViewStyle">#style/CustomTextViewAppearance1</item>
</style>
<style name="CustomTextViewAppearance1">
<item name="android:textSize">10dip</item>
</style>
<style name="CustomTextViewAppearance2">
<item name="android:textSize">30dip</item>
</style>
Now in the layout all textViews are like CustomTextViewAppearance2 (because this is set as standard in this style. And the textViews that should use the other style write into the definition:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="blablabla"
style="?mainButtonTextView"/>
When you now call .setTheme (after restart the activity) the appearance of the textviews switch. Like this method you can define as many different types of View styles and switch between them only by calling .setTheme.
Unfortunately, styles are static once they are defined. To have an entire cascade of styles modified programmatically, you would have to change the definition of the style itself. Instead, all you can do is change the style that is assigned to a TextView (or whatever style-able object), as outlined in the question I linked to in my comment above.

Categories

Resources