Custom views and defStyleAttr - android

I'm struggling with custom views defStyleAttr. (Short note I'm using a Preference as example cause it's the same way Google uses it)
So for almost every View or Preference that is provided by Android you'll have a constructor like this:
public SeekBarPreference(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.seekBarPreferenceStyle);
}
This defines the default style attribute to be R.attr.seekBarPreferenceStyle.
If you now look into the definition you'll find this:
<attr name="seekBarPreferenceStyle" format="reference" />
Until now everything is clear. But this attribute is somehow linked to a theme:
<resources>
<style name="PreferenceThemeOverlay">
<!-- ... -->
<item name="seekBarPreferenceStyle">#style/Preference.SeekBarPreference.Material</item>
<!-- ... -->
</style>
<!-- ... -->
</resources>
Which then finally links a style with the needed layout resource id that will be handed over to the super class to be inflated:
<style name="Preference.SeekBarPreference.Material">
<item name="android:layout">#layout/preference_widget_seekbar_material</item>
<!-- ... -->
</style>
Unfortunately I wasn't able to find a hint on how the theme PreferenceThemeOverlay is linked to the attribute seekBarPreferenceStyle.
So how are these two linked?

I finally found an answer that explained the basics you need to know.
Custom View
For the examples I use SeekBarPreference as a custom object (Preference and View are very similar)
So in short there are two ways to set your default style.
Either set a custom theme to your activity (or the like) that links something to your custom style (seekBarPreferenceStyle) or set the style directly by the style XML attribute.
Theme
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="seekBarPreferenceStyle">#style/LINK_TO_DEFINING_STYLE</item>
</style>
AndroidManifest.xml
<activity android:name=".SomeActivity" android:theme="#style/AppTheme">
Style attribute
some.xml
<SeekBarPreference
[...]
style="#style/LINK_TO_DEFINING_STYLE"
[...] />
Androids Way
But I wanted to know exactly how all of it is connected to then work without any style attributes in XML files for SeekBarPreference or other Preference and View objects provided by Android.
So (via Android Studio) I followed Theme.AppCompat.Light.DarkActionBar down to its parent Theme.Holo.Light and look what I found there:
<!-- ... -->
<item name="seekBarPreferenceStyle">#style/Preference.Holo.SeekBarPreference</item>
<!-- ... -->
Linking to this style which links the layout resource:
<style name="Preference.Holo.SeekBarPreference">
<item name="layout">#layout/preference_widget_seekbar</item>
</style>
And to finally bring some more confusion to you again, Android seems to link a the Material style from the question instead of the Holo theme from the answer to the default theme (be it DeviceDefault or something else).
So if you got any clue on this please feel free to add to the comments :)

Related

How can you locate the default style for a widget (i.e. AppCompatEditText)

UPDATE: As pointed out in the comments, 'Widget.AppCompat.EditText' is the correct parent style for an AppCompatEditText subclass. In my case, the real issue was I had forgotten to assign a value to our control's default style attribute in our theme, so our control wasn't getting any style to use as a default.
However, this question still could use an answer as to how one properly identifies which style to use as a parent when defining your own default styles when subclassing the standard controls. As such, I've also renamed its title.
As such, I'm leaving this open in hopes someone can answer that question since it will help any who wish to do something similar.
We're trying to define a common look-and-feel for all AppCompatEditText controls used throughout the app. As such, rather than having to manually apply the 'style' attribute on each usage, we're instead trying to replace the default style with our own.
Replacing the default style is actually the easy part. What isn't is knowing what the parent style for our style should be set to so we still have all aspects of the original style which we haven't explicitly overwritten with those in ours.
Digging in the source code for AppCompatEditText, it shows the default style to be stored in R.attr.editTextStyle but I'm not sure where now to look to see what value is stored in it.
Experimenting too didn't get us anywhere. No matter what we have tried so far, we lose the default appearance completely. No underline, no background, no padding, nothing. Just the values we've set, which means it's not picking up the parent style.
We've tried the following without success...
<style name="ZinEditText" parent="android:Widget.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Widget.AppCompat.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Base.V7.Widget.AppCompat.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Widget.Holo.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
As I said, none of the above seemed to work.
So how does one find the actual parent style to use?
To address the immediate issue, the default style for an AppCompatEditText is Widget.AppCompat.EditText. The second example you've shown is the correct one:
<style name="ZinEditText" parent="Widget.AppCompat.EditText">
...
This needs to be set as the editTextStyle in your app theme.
<style name="AppTheme" parent="#style/Theme.AppCompat">
<item name="editTextStyle">#style/ZinEditText</item>
...
Finding these default styles and attributes is not well documented anywhere officially, as far as I'm aware. The official documentation for Styles and Themes simply directs one to the various R.attr pages for the framework and support packages, to "discover" what's available. However, a generally reliable way to find this for most Views that allow a default style is to inspect the source code.
A View subclass will often implement at least three constructors: one that takes only a Context; one that takes a Context and an AttributeSet; and one that takes a Context, an AttributeSet, and an int for defStyleAttr, a default style attribute. This attribute is what we're looking for. It will usually have a sensible name, like editTextStyle, textViewStyle, checkboxStyle, etc. If you already know the name, you can skip checking the View class for it.
In Views that chain their constructors, this attribute will be normally be in the call to the three-parameter constructor from the two-parameter one. In AppCompatEditText, we can see that the name of this attribute is editTextStyle.
public AppCompatEditText(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.editTextStyle);
}
After we've got the name for the attribute, we then head to the res/values/ directory for the platform or support package the View is in. The default value will be in the relevant themes*.xml file for your app's parent theme.
For the platform themes, there is a base themes.xml, and a few others for specific theme versions, such as Holo and Material.
For support library Views, these theme files will be under the package-specific res/values/ directory, and the default attribute value may be in themes.xml or themes_base.xml.
In v7 appcompat, our app's exact parent theme is likely in v7/appcompat/res/values/themes.xml, though most of the themes there are just direct aliases for base themes; i.e., they don't override any of their parents' attribute values. The default for AppCompatEditText is actually in v7/appcompat/res/values/themes_base.xml. There are separate entries for different themes - the regular, and the light - but they are both the same.
<item name="editTextStyle">#style/Widget.AppCompat.EditText</item>
This is enough to determine which style to use as our parent, but should we want to check out the style specifics, we can then refer to v7/appcompat/res/values/styles.xml, where we find that style's parent:
<style name="Widget.AppCompat.EditText" parent="Base.Widget.AppCompat.EditText"/>
which leads us to v7/appcompat/res/values/styles_base.xml:
<style name="Base.Widget.AppCompat.EditText" parent="Base.V7.Widget.AppCompat.EditText" />
<style name="Base.V7.Widget.AppCompat.EditText" parent="android:Widget.EditText">
<item name="android:background">?attr/editTextBackground</item>
<item name="android:textColor">?attr/editTextColor</item>
<item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
</style>

Themes in android

A create a simple Theme as
<style name='one'>
<item name='android:textColor'>#eea</item>
<item name='android:textSize'>20sp</item>
</style>
However on viewing in the emulator the screen goes black.when i do not apply theme the screen has a white background .
what really happens here.i am just starting with android.
In addition ,if a apply a theme to my activity then the attributes of the theme applies to all components of my activity say button,textfields and edittexts .
why would i then write
android:textSize=?android:textSize
to reference value from the theme for any button in my layout when the same value would already be applying.
is the syntax above the correct way to reference an attribute from my theme to assign to attribute for any view in my layout.
thanks
tejinder
Yeah, so you need to do a little more reading.
Let's start with the basics,
You need to understand the differente betweent an Attribute, a Style, and a Theme.
An Attribute is something that can be styled. For instance: android:textSize is an attribute that can have any value.
A Style is a set of specific attributes that will be applied to a Widget. They are defined
in your /values/styles.xml
For instance:
<style name="normalTextThin" parent="android:Widget.Holo.Light.TextView">
<item name="android:gravity">left|center_vertical</item>
<item name="android:padding">8dp</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">16sp</item>
</style>
The styles can be applied either as part of a theme or directly as theme-independent.
Theme-indepentent styling of a widget is like this:
<TextView
android:id="#+id/text"
style="#style/normalTextThin"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
You are then theming only that one TextView.
A Theme is a collection of Styles that can be applied to a part of your UI, such a a whole Activity, or your whole Application.
For instance:
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:editTextStyle">#style/EditTextAppTheme</item>
<item name="android:buttonStyle">#style/ButtonAppTheme</item>
<item name="android:imageButtonStyle">#style/ImageButtonAppTheme</item>
</style>
Here, we are declaring that all EditText in your application will use the style named EditTextAppTheme, and so forth and on. When done like this, in order to actually have the theme be active, you declare it in the manifest:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
That means that you are not required to declare the style on each widget you create.
<EditText
android:id="#+id/input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/hint_search">
<requestFocus />
</EditText>
That widget right there would already be styled using EditTextAppTheme without the need of you explicitely declaring so.
I recommend you try to read on what attributes can be styled, how to style them, and so forth and on.
If you don't want to though, it's fine, you can still get a lot done with the following tools for styling:
ActionBarStyleGenerator to help you create styles for the ActionBar.
Android Holo Colors to help you style standard widgets.
Hope that helps.
Additional Info
Let me clarify on the whole ?attr/attributeName
The ? means that the system will choose the specific attributeName value for the current Configuration (not specific to different themes). This should be used only when you want the value to be different on different configurations. For example:
?android:attr/actionBarSize
This line is a dimension, and it will be different not based on the current theme, but on the current device screen size and orientation (values, values-land, values-sw600dp).
It's important to know that specifying ?android: means you are accessing preset Android values, not yours. If you have or want to create and use your own attribute values for specific configurations, you must do the following:
Create a file named attrs.xml on your /values/ folder.
Declare the desired custom attribute:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<attr name="my_custom_attr" format="reference" />
</resources>
Declare a value for the custom attribute, let's say on your own theme.
<style name="AppTheme" parent="android:Theme.Light">
<item name="my_custom_attr">#resource_type/resource_name</item>
<item name="android:editTextStyle">#style/EditTextAppTheme</item>
<item name="android:buttonStyle">#style/ButtonAppTheme</item>
<item name="android:imageButtonStyle">#style/ImageButtonAppTheme</item>
</style>
And then you can use it on the Widget you'd like:
Hope that clears things out.
EDIT 2
For a better answer to your question, please update your question. And like I said, read more on how to properly create styles.
The Theme named 'one', what do you want to apply it to? An activity, a Widget, the whole Application?
How are you applying the theme? Show the lines of code where you specify the usage of theme 'one'.
Your theme as you specified is simply not a properly constructed theme/style.
<style name='one'>
<item name='android:textColor'>#eea</item>
<item name='android:textSize'>20sp</item>
</style>
This says absolutely nothing, and it is definitely not suitable for an Activity-level theme. The reason you specify a parent is so your theme can inherit all of the attributes from the parent, and then you specifiy which ones to change.
For instance, if you want to use your theme and have a light background, do this:
<style name='one' parent="android:Theme.Holo.Light>
<item name='android:textColor'>#eea</item>
<item name='android:textSize'>20sp</item>
</style>
But even here, despite the fact that it will apply, you don't want to have the same text color and size for the whole application do you? That'd be nonsense, different text color and sizes account for a big part of the user experience, so rather than setting those values from what we can refer to as the main style, we can create substyles and apply them to certain widgets.
I can't really go any more detailed that what I already have, the above explains how to accomplish Widget-specific styling, and activity/application level theming.
For a complete start-up guide, read the Android Developer Site, try the test styles declared there, see how they work, and until then try to create your own, don't try to create something out of nowhere if no reading has been made.

Android - Error inflating SimonVT NumberPicker class in my layout xml

I've been at this for days now, and I am at the point of giving up, so any help is much appreciated!
I've been trying to implement the simonVT numberpicker in my android app. Completely new to android, so including the library, referencing this library and getting everything to compile has been a few days mission in itself. Now I finally have everything compiling I get the following error at runtime:
04-06 10:58:37.126: E/AndroidRuntime(14324): java.lang.RuntimeException:
Unable to start activity ComponentInfo{com.example.goalminder/com.example.goalminder.AddGoal}:
android.view.InflateException: Binary XML file line #81:
Error inflating class net.simonvt.numberpicker.NumberPicker
Here is the opening of my layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/net.simonvt.numberpicker"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
NB - The 'xmlns:app' part above has a yellow warning marker - it's not being used. I included this per another stackoverflow answer re. a similar problem. Have left in to discourage this suggestion.
Here is the xml for the numberpicker:
<net.simonvt.numberpicker.NumberPicker
android:id="#+id/dayPicker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginRight="10dp"
android:layout_weight="1"/>
I have included the theme as instructed by Simon in my theme file. I wasn't really sure what name to give it, so I called it 'NumberPicker':
<resources>
<!-- Copy one of these attributes to your own theme (choose either dark or light).
<item name="numberPickerStyle">#style/NPWidget.Holo.NumberPicker</item>
<item name="numberPickerStyle">#style/NPWidget.Holo.Light.NumberPicker</item>
-->
<style name="NumberPicker" parent="android:Theme">
<item name="numberPickerStyle">#style/NPWidget.Holo.NumberPicker</item>
</style>
<style name="NumberPicker" parent="android:Theme.Light">
<item name="numberPickerStyle">#style/NPWidget.Holo.Light.NumberPicker</item>
</style>
</resources>
I have also added the following to my android manifest as a child of application:
<activity
android:name="net.simonvt.numberpicker.Numberpicker" />
<activity
android:name="net.simonvt.numberpicker.Scroller" />
I've been all over stackoverflow, so what we have above is a scatter gun approach of everything I have seen recommended so. As stated before, I'm floundering with this and am close to implementing a standard ugly list.
NB - I got all this working with the native android implementation of Numberpicker. I want to use Simon VT's backport version however as I will be looking to support API < 11, which includes Gingerbread which I believe has a 39.7% distribution. Please let me know if you think I don't need to support this far back.
you need add theme for the activity on AndroidManifest.xml:
Example:
<activity android:name="yourActivity" android:theme="#style/SampleTheme.Light"/>
If you don't want to create a theme for your own project, you may do the following to the source code of numberpicker to set it to use the default theme NPWidget_Holo_numberPicker.
Replace the constructor with the following
public NumberPicker(Context context, AttributeSet attrs) {
this(context, attrs, R.style.NPWidget_Holo_NumberPicker);
}
then change the assignment of TypedArray attributesArray to the following:
TypedArray attributesArray = context.obtainStyledAttributes(
attrs, R.styleable.NumberPicker, 0, defStyle);
See Simon's usage notes:
Requires adding a single attribute to your theme. Check the sample app for how this is done.
values/theme.xml:
<style name="SampleTheme" parent="android:Theme">
<item name="numberPickerStyle">#style/NPWidget.Holo.NumberPicker</item>
</style>
values-v11/themes.xml:
<style name="SampleTheme" parent="android:Theme.Holo">
<item name="numberPickerStyle">#style/NPWidget.Holo.NumberPicker</item>
</style>
Try replacing net.simonvt.numberpicker.NumberPicker with com.your.package.NumberPicker.
I was having practically the same problem, I was getting the error
11-18 21:13:18.627: W/ResourceType(13799): No package identifier when getting value for resource number 0x00000000
I finally realised that I had to add the style item into my own style definitions (as Paul Lammertsma shows above) as I was just copy/pasting SimonVT's styles, which of course my application wasn't using:
<style parent="#android:style/Theme.Holo.NoActionBar.Fullscreen" name="NoActionBar">
<item name="numberPickerStyle">#style/NPWidget.Holo.NumberPicker</item>
</style>
Then, after it still not working, I found I'd completely missed a themes.xml file (I have three for different API levels).

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.

How do I cascade a style by theme in android

Basically, I'd like to have a single layout that I can skin differently on the theme. Many examples and entries on this site seem dance around the issue a little so I'm not entirely certain it can be done. Or I just don't get it.
Here's the concept.
Let's say my app is sports-related.. the app has a default them of 'SportTheme'
I'd like users also to say they want the 'Football' or 'Baseball' theme, and on designated <TextView> elements, I'd like the text (defaults to 'Sport') to change to 'Football' or 'Baseball' given the overall theme applied to the activity?
in strings.xml
<string name="label_sport">Sport</string>
<string name="label_football">Football</string>
<string name="label_baseball">Baseball</string>
in activityA.java - The important thing here is that the theme is set for the activity (or application is fine, too).
#Override
protected void onCreate(Bundle savedInstanceState)
{
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
this.setContentView(R.layout.layout_a);
switch (user.ThemePreference)
{
case FOOTBALL_THEME:
this.setTheme(R.style.FootballTheme);
break;
case BASEBALL_THEME:
this.setTheme(R.style.BaseballTheme);
break;
default:
this.setTheme(R.style.SportTheme);
break;
}
}
in layout_a.xml
...
<TextView
android:id="#+id/tvSport"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="#string/label_sport"
android:style="#style/SportLabel"></TextView>
What do I do in themes/styles? Something like this? The important thing here is the text in the TextView. I'll be using the same textView in several different activities throughout the application.
<theme name="SportTheme" parent="android:Theme" />
<theme name="FootballTheme" parent="SportTheme">
<item name="android:background">#color/brown</item>
</theme>
<theme name="BaseballTheme" parent="SportTheme">
<item name="android:background">#color/green</item>
</theme>
<theme name="SportTheme.SportLabel">
<item name="android:text">#string/label_sport</item>
</theme>
<theme name="FootballTheme.SportLabel">
<item name="android:text">#string/label_football</item>
<item name="android:textColor">#color/black</item>
</theme>
<theme name="BaseBallTheme.SportLabel">
<item name="android:text">#string/label_baseball</item>
<item name="android:textColor">#color/white</item>
</theme>
Thanks for any insight you can provide
To customize your UI with themes you need to define attributes you want to customize inside your themes and use references to these attributes in layouts (e.g. attr/backgroundColor).
There're three files in Android sources which are used for this purpose: attrs.xml, styles.xml and themes.xml. If you need some custom attributes for customization then you should declare them in attrs.xml. If you're going to use only predefined Android attributes then you don't need to create this file.
<declare-styleable name="SportTheme">
<attr name="customAttribute" format="color" />
<attr name="sportLabelStyle" format="reference" />
</declare-styleable>
The styles.xml file is used for defining sets of attribute values. For example you can define different style sets for each widget.
<style name="Widget.TextView.SportLabel" parent="#android:style/Widget.TextView">
<item name="android:textColor">#android:color/white</item>
<item name="android:textSize">20sp</item>
</style>
The themes.xml is the main file used for customizing. All themes are usually defined in this file. You can customize something in several ways. For example you can define a default value in the theme and reference it from a layout. Also you can define a reference to a style.
<style name="Theme.FootballTheme" parent="#android:style/Theme">
<!-- define value for predefined Android attribute -->
<item name="android:colorBackground">#android:color/white</item>
<!-- define value for custom attribute -->
<item name="customAttribute">#android:color/black</item>
<!-- define reference to a style -->
<item name="sportLabelStyle">#style/Widget.TextView.SportLabel</item>
</style>
layout.xml
<TextView
android:background="?android:attr/colorBackground"
android:textColor="?attr/customAttribute"
style="?attr/sportLabelStyle" />
Notice that style is used without the android namespace. That's not a typo.
So if you want to customize your layout using themes you can create several themes and define default values for attributes and attribute sets (styles) and reference these values using
?[android:]attr/attributeName
Sounds difficult but it's not really. You can use Android resources as an example of styling.
Please ask your question if something is not clear.
I have written a blog post about Themes which may help you. There is also a series of article on Custom Controls which explains how to create a custom control which is themeable, and this provides additional information about how Android themes work.

Categories

Resources