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 the above screenshots from the sample application, you can see the exact same layout rendered differently by applying different themes.
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. <?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme" parent="android:Theme">
<item name="android:windowTitleSize">20dip</item>
</style>
</resources>
<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.<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/Theme">
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 to setContentView()
. 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
: <item name="pageMargin">2sp</item>
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.Create a file called
attrs.xml
in res/values/
. Here you will create your style attributes, which are any customizable attributes you would like for your theme to define. Below, I have created a new attribute called pageMargin
, which I will use to define margins.<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="pageMargin" format="reference|dimension" />
</resources>
<resources>
<attr name="pageMargin" format="reference|dimension" />
</resources>
Now, the build system will not throw an error anymore because
Now, I could set the margins in my views by referencing a single constant, instead of putting the same value piecemeal around the code:
pageMargin
is now defined. The format
attribute indicates what type of values I can define for pageMargin
; in this case, either a reference to another attribute, or a dimension such as 2sp
or 4px
. Other examples of possible formats are color
, boolean
, integer
, and float
. Now, I could set the margins in my views by referencing a single constant, instead of putting the same value piecemeal around the code:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello"
android:layout_margin="?pageMargin"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello"
android:layout_margin="?pageMargin"/>
I can change
pageMargin
in one place and all of the margins in my views which reference this attribute will be changed. Unfortunately, this method of defining your view's styles has some issues. If you open this view in the Eclipse layout editor, you will see an error: Unable to resolve dimension value "?pageMargin" in attribute "layout_margin"
. In order to make any use of these attributes, we need to apply the theme to our activities, and this doesn't work in the layout editor.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 titleTextViews
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. <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/title_text"
style="?textTitle"/>
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 the textTitle
style, such as android:textColor
and android:textSize
.When using the
style
attribute in your layout files, the views will appear plain when using the Eclipse layout editor. However, when the theme is applied in your application, your custom styles will be applied.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 inthemes.xml
. <style name="Theme.White">
<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>
<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's onCreate()
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 asMyTheme.Blue
, then you will create a theme calledMyTheme_Blue
whose parent is the themeMyTheme
. 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 inthemes.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.
72 comments:
Nice but i though you were going to post something on ColorStateList but this clear me some doubts... thanks
Great tutorial, i was waiting for that for months.
@Jose Espinoza
There are some examples of the ColorStateList in the sample program. See the res/color/ directory. Basically, use the ColorStateList anywhere you'd use a regular color, and the colors will change depending on whether the containing View is focused, pressed, etc.
This is a brilliant tutorial Matt, Thanks
Nice explanation.
Though I have not tried, but i assume the style overriding works in a similar fashion as web or are there some gotchas?
Extremely useful! Was exactly the use case I was looking at. Julia Child would be proud...
This was an amazing example. Clean, clear and functional! Thank you so much!
Can you help me i want to modify theme for DialogPrefernce used in ListPreference
want to change radio button images and background of dialog.
There is attribute defined in attrs.xml
so how do i find out the theme defined for the dialog?
Great tutorial. Thanks! by the way what do you use to do your syntax highlighting?
@Eric Harlow Actually, it's just Eclipse syntax highlighting. When you copy anything from the Eclipse editor, it copies it in RTF format. Then, I run a script which formats it in Blogger.
this is exactly what i want, but i'm having trouble. the only diff is that i'm trying this with a widget.
i set the theme at the application level in the manifest, and tried calling Context.setTheme() from the widget's buildUpdate() method. neither has an effect. the view widget just don't see the style="?whatever" styles, although there is no error at design time from eclipse.
any ideas?
This was by far the most useful tutorial on themes in Android I've found yet. Thank you!
I was in the middle of implementing themes based off of this when I ran into this problem and was hoping you could shed some light on my situation
http://stackoverflow.com/questions/4035936/tag-that-references-current-theme-in-xml-causes-force-close
this is good meat on themes for a hungry man like me.
How can one also change the default string with the theme? So, for example, the title bar could say "Blue Theme" or "Gray Theme" when you switch themes. Is it possible to define this in the XML?
Indeed usefull,easy for all developers. thanks
How I do apply a custom theme to whole my android user interface on my phone?
Sometimes I want black on white instead of white on black
Awesome, thanks a lot it really helps!!!
This a good example. But if the themes are not pre-define in theme.xml, how to implement it. That is to say, the themes are from another apk, not in the main apk. The example is like HCT HD Skin.
Thank u dude.Really very nice example with good explanation
great tutorial!
i'm having the problem of when i apply style to listView it breaks on onClick events.
https://groups.google.com/group/android-developers/browse_thread/thread/46bb94300cf4bf75
any ideas?
Thanks a lot very simple and helpful
Hi,
thank's for this tutorial.
Did you try custom style/theme for spinner too ?
When I modify spinner background (by xml attribute), it works but the selector arrow (on the right of first item when spinner is collapsed) becomes invisible ...
Same unexpected result with spinnerStyle attribute.
I am using API level 3 (Android 1.5 target).
Thank's for any idea.
Thanks for this post! It is very helpful.
Awesome man.. i owe you a beer...
I have been looking for a way to do this for this afternoon.
Thanks a bunch! That is a life saver!
Richard L.
http://android9patch.blogspot.com/
what is your email id , so that i can contact you.
Hi Mat,
Will you please add Tabwidget style to the Theme.white and Theme.blue. I am using your theme having a listview inside a tabwidget and the colors dont match.
Thanks
Raianeh
Hi Matt Quigley !
Thanks for the tutorial.
I'm following your tutorial. And here I have two themes in my application. I tried to adapt my application but in the Util class when i put activity.setTheme (R.style ta ... the theme xml on my values does not appear. In your example appears Theme.White and Theme.Blue. You know how to solve this problem ?
hello matt if I have more than one activity how can I change the theme at all?
Thanks for the article!
Has anyone figured out how to either share themes across apps dynamically or load themes from a website?
The idea is that other developers could create a module to theme your app.
I love you and want to have your babies. PS. Can I use this in one of my apps?
Best tutorial , i have ever seen..
Great Work........
Great tutorial! It help me a lot. Thank you
Nice tutorial.
Thanks!
I've sth like this applied to TextView textColor.
But it's always red instead of my colors. When I set textColor just to ?foreground color changes to foreground correctly. So there is issue with that selector? It doesn't know about references to the actual color?
I've sth like this applied to TextView textColor.
selector xmlns:android="http://schemas.android.com/apk/res/android">
item android:state_pressed="true" android:color="?background"/>
item android:state_focused="true" android:color="?background"/>
item android:color="?foreground"/>
/selector>
But it's always red instead of my colors. When I set textColor just to ?foreground color changes to foreground correctly. So there is issue with that selector? It doesn't know about references to the actual color?
Great information! After implementing into an actual application I noticed the call to "Utils.onActivityCreateSetTheme(this)" would not work correctly if placed after the "super.onCreate(savedInstanceState);" line in my Activity "onCreate" routine. After searching the Internet I discovered placing the line before "super.onCreate(savedInstanceState);" worked fine.
Just as here in the example textview styles are being changed dynamically... Is it possible to use the similar technique with action bar in ICS that too without relaunching the activity..
Hello,i'm so much thankful to the author of this blog...
Bcoz this thread gave me not only an answer to my search for android design using themes,but also the method for creating and returning the android widgets from a POJO without extending Activity.Thank u a lot...
as I c in your example, pageMargin attribute is not actually used, and I was unable to modify your application to reference it to set, for example, paddings of main layout.
This causes "java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x2"
From the other hand, referencing any attribute declared in android package works ok
I spent lot of time googling for this problem but just found number of unanswered questions like this.
This was by far the most useful tutorial on themes in Android I've found yet. Thank you!
Thanks
Awesome tutorial .I was Just searching the source codes since long time & thanks a lot for the details and step by step method you have explained here .
Hi there,
at what API level does this start?
Cheers
Cool post, I was look for something about Themes for Android App.
Congratulations, It's works!
Cheers.
Marco Maddo
Brazil
http://www.4android.com.br
Holy... Man, works like magic! Thanks a lot!
It is useful. I did follow the guideline and I have a perfect setup.
Thanks
Thanks a lot for such a good post
Learn how to create style for a view in Android visit here on
www.driveandroid.com
This is bad example. Instead of code beiing shown on wep page one must download it, unzip and then view it with some tool. Waste of time.
But I believe it was done with best intensions.
Nice tutorial. In my case, I would like to programmatically create dynamic list populated from database. I am able to create the text view but I can’t reproduce the View. All stuck with java.lang.NullPointerException. The Code I use is :
View vi = new View(Home.this);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) vi.getLayoutParams();
params.height = 1;
vi.setLayoutParams(params);
linearLayout.addView(vi);
This tutorial is a GOD SEND!! Thank you so much for making it so easy to understand for a designer like myself!! XXXX
Thank you for this useful tutorial.
Nice tutorial.
In my case, I am creating some layouts dynamically depending on the conditions. So how can I handle theme change in such cases.
For example, in one of my activity, I am creating the whole layout dynamically, which includes LinearLayout,Button and other widgets. Please suggest me to do this smoothly.
Thanks
Thank you for this useful tutorial. :D
So, you wrote this almost 4 years ago. What have you learned since then that would make this information better? I'd love to see a deeper dive into the subject, how/why it works, etc.
Great tutorial, Thank you very much!
Great!!!ou
Very Nice!!!
you save my life!!!
Hi Matt, your tutorial help me a lot to understand themes & styles :-)
Many thanks !!!
@+Mat
At Webnet, we have effect of a force and acclaimed custom android app development affiliation really. Today, we are fulfilled to say that we have shockingly specific fulfilled clients who trust us with their work understanding that all they will get from us is yet the best quality android applications.
appdroid
best-whatspp-group-names
thanlk youi admin
clever wifi names
thank you admin
Awesome tutorial .I was Just searching the source codes since long time & thanks a lot for the details and step by step method you have explained here ..
for banking related content you can go through following website
marksbooster.com
Nicely explained it...good one and banking related content you can follow below links.
marksbooster.com
Importantn Awards and their related fields
highest civilian awards of different countries list
small finance banks and their headquarters
list-of-payments-banks-in-india-and-their-headquarters-heads-and-taglines
list-indian-states-current-chief-ministers-governors-2018
Useful tutorial. Thanks.
Hey, very nice site. I came across this on Google, and I am stoked that I did. I will definitely be coming back here more often. Wish I could add to the conversation and bring a bit more to the table, but am just taking in as much info as I can at the moment. Thanks for sharing.
Dai Software
http://gadgetssai.blogspot.com/2017/12/funny-wi-fi-names-for-your-home-router.html
You can use this trippy backgrounds for themes it's free and useful thank you
Great Article
IEEE Android Projects for CSE
Java Training in Chennai
FInal Year Project Centers in Chennai
Java Training in Chennai
Post a Comment