感谢:http://www.androidengineer.com/2010/06/using-themes-in-android-applications.html
Using Themes in Android Applications
As a developer, I understand how developers think when going about creating an application. We start with an idea, with an end goal in mind, and start putting together pieces from the bottom-up until we reach our goal. Like any engineer, we enjoy playing with the individual parts, tinkering with building blocks, until we have put them together to create something fantastic that works. As much fun as this may be, experience shows that throwing together these building blocks without using a proper framework to build them is leads to bad designs, and applications which are difficult to maintain and change later on.
When it comes to design, we don't think in the same manner as a more artistically inclined designer would. We work from the bottom up, and they work from the top down. They will work with the entire endeavor as a whole, seeing the final product working without bothering with the individual nuances of the sum of its parts. In their mind, those parts just work; in the engineer's mind, we think of how we can get those parts to work. I believe this could be said about many types of work involving engineers and artists, like websites and buildings.
If we, the software developer, use too many individual parts to create our app that have been molded on their own, without concern for the other parts they will be fitting into, it is much harder to make them fit in the first place, and especially to later make changes to them. Besides, the less moving parts the better; as a software developer, it is simply good design to create your user interface with building blocks which conform together instead of changing numbers, colors, etc. here and there to force everything to eventually look good.
What I am dealing with here is UI; the graphical representation of your app. More specifically, UI design in Android applications.
Use Styles in UI
In Android, you use Views to design your Activities. An Activity is the central class which handles a specific, well, activity, in your application. The class which handles the visual representation of activities is View. The Views themselves can be created programmatically within the Activity, but one should only do so in rare circumstances. The better way to define them is using XML layout files.
The Android SDK for Eclipse gives us a nice visual editor to design views, which directly manipulates the XML for us. The layout editor does not, unfortunately, give an easy way to customize the look and feel of the application. By look and feel I mean the colors, the margins, the fonts, and any attributes that contribute to how all of the views display.
Remember in your beginner computer science classes learning about constants, and why you should use them? One reason was that if you use a constant, you can reuse it in many places, but only have to change it one place. In the same manner, we should be using constants to define the way our application looks, so we can easily change it from one central place, in order to change the entire application. (On a side note, if you've ever dealt with creating web pages, you probably have realized that it is far better to use CSS than to change the attributes of individual elements of your HTML pages).
Creating Themes 创建主题
Finally, onto the real meat of how to use themes! What I will show you here is how to define a theme in your resources in an XML file, how to define attributes of the theme, how to apply those to your layout files, and finally how to dynamically change the theme of an activity.Create a file themes.xml in res/values/. Here you will create the name of your theme, and any customizable attributes you would like for your theme to define.
<resources>
<style name="Theme" parent="android:Theme">
<item name="android:windowTitleSize">20dip</item>
</style>
</resources>
Above you see I have created a theme called Theme, whose parent is the default Android theme. There is a custom attribute called pageMargin, and also a default OS attribute android:windowTitleSize which has been overridden. I recommend you set the theme's parent to the default Android OS theme, in order to inherit all of the system attributes. Otherwise, unless you only use your own custom views, the system views such as ListView will be missing attributes which are defined in the system theme which are not defined in your own theme. This will cause funny layout issues at best, but at worst it will cause exceptions due to attributes that the views could not find. Remember, not all Android devices are built the same.
Setting the Theme 设置主题
We can set the theme of either our application or individual activities in the manifest file. If you don't need to have more than one theme at all in your application, just set the theme of the activity. Otherwise, you can define themes specific to an activity.android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/Theme">
You can also set the theme of an activity programmatically. This is done by calling setTheme() in the activity's onCreate() method, before any call tosetContentView(). Note that this approach should typically be avoided, especially from the main activities of your application, because the theme you set here may not be used for any animations the system uses to show the activity (which is done before your activity starts). The exception to this rule is if you want to set your themes dynamically, such as in the case where the application can have more than one theme.
Custom Attributes
Although it is nice to be able to override the default system properties in some cases, what we'd really like to do is define custom properties of our own in our application's layouts. Say we wanted the margins of all of our activities to be a certain dimension. If we define it in one place, we can change it all at once. Below is an example of a custom attribute added to our custom theme inthemes.xml which we can use to define a property called pageMargin:If you simply copy the above text into your new file themes.xml, you will get a build error Error: No resource found that matches the given name: attr 'pageMargin'. This is because we have not defined what pageMargin is to the build system. android:windowTitleSize is OK, because it is already defined in the Android SDK.
<resources>
<attr name="pageMargin" format="reference|dimension" />
</resources>
Now, I could set the margins in my views by referencing a single constant, instead of putting the same value piecemeal around the code:
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello"
android:layout_margin="?pageMargin"/>
If you'd like to see some more examples, you can look at the Android OS source code default res directory, in particular themes.xml, styles.xml, and attrs.xml.
Styles
A more sophisticated method to setting the properties of your views in the layout is give a view a style, which is a group of attributes, instead of defining the values of individual attributes. For example, you could set the styles of all of your title TextViews to have the style textTitle. This style could have custom text color, font, and margin properties. In addition, the layouts can be safely edited in the Eclipse layout editor, because the style attribute is not needed to render the views.android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/title_text"
style="?textTitle"/>
Now this TextView has a custom style. You can assign multiple attributes to thetextTitle style, such as android:textColor and android:textSize.
Dynamic Themes 动态设置主题
If you want your application to have a customizable look and feel, then you will want to create multiple styles. An example of this is given in the sample application below. To have multiple themes, you will want to create multiple theme definitions in themes.xml.<item name="textTitle">@style/text_title_wh</item>
<item name="textSubheader">@style/text_subheader_wh</item>
</style>
<style name="Theme.Blue">
<item name="textTitle">@style/text_title_bl</item>
<item name="textSubheader">@style/text_subheader_bl</item>
</style>
To set the theme dynamically at runtime, call setTheme() in your activity'sonCreate() method, before calling setContentView(). To change the theme, you simply need to restart your activity.
If you have a theme name with a dot in it, such as MyTheme.Blue, then you will create a theme called MyTheme_Blue whose parent is the theme MyTheme. It is a convenient way to inherit the properties of a parent theme.
Sample Application 简单的例子
This sample program shows how to use custom themes. The application has one Activity with one corresponding layout file. Most of the views in the layout have a custom style. You can change the style dynamically by pressing the buttons at the bottom of the screen.Project Source Code - Themes.zip (16.4 Kb)
Project Package - Themes.apk (28.1 Kb)
Screenshots
Conclusion 总结
1. Define one or more themes in themes.xml and set the definitions of your styles there.2. Define custom attributes, a.k.a. custom styles, in attrs.xml.
3. Describe what the values of your custom styles are in styles.xml.
4. In your layout files, give your views a style attribute, which has a custom style name as their values.
5. Set the theme of your application or activity in either AndroidManifest.xml or in the Activity's onCreate().
As an Android application programmer you should now know how to stop placing look and feel attributes directly into your layout files and start using styles to design your UI.