I would like my application to be available under different brandings - this means that it must be possible to easily change background bitmaps in few places, but also change text resources.
My plan is to use themes and styles, I know they can be used for switching bitmaps but will they allow me to change also texts in TextViews for example?
Is it also possible to specify in style or theme a text identifier and later dynamically read it in code?
[EDIT]
After some investigation, of course texts can be substituted with styles. Another problem that comes with application branding is the need to change package name - otherwise Google Play wont accept our branded application.
[EDIT]
After more investigation, below I include small sample on how to add two switchable themes that will allow to substitude drawable in activity layout, and text resource in textview. Whats left is to call setTheme(R.style.Theme1); or setTheme(R.style.Theme2); in onCreate before setContentView.
<-- attrs.xml />
<resources>
<attr name="ProductName" format="reference"/>
<attr name="ProductBackground" format="integer"/>
</resources>
<-- styles.xml />
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme1" parent="android:Theme.Light">
<item name="ProductName">#string/s_product_1_name</item>
<item name="ProductBackground">#drawable/back_1_vga</item>
</style>
<style name="Theme2" parent="android:Theme.Light" >
<item name="ProductName">#string/s_product_2_name</item>
<item name="ProductBackground">#drawable/back_2_vga</item>
</style>
</resources>
<-- my activity layout />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?ProductBackground"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
tools:context=".MainActivity"
android:background="#ff0000"
android:text="?ProductName"
/>
</RelativeLayout>
There are two aproaches to make different brandings of you app:
1) Split your app into multiple library projects, common code is in lets say common_lib library project, and all your brandings are in separate projects using common_lib but changing some of the resources, like strings, some drawables, also package name. This is the aproach we have choosen in our app.
2) Use gradle product flavors: http://developer.android.com/sdk/installing/studio-build.html, I think this should now be the prefered solution.
Related
I want to style all my ImageButtons in a theme. After searching for quite some time I found the solution to my problem. But I don't know why it works like it does.
My main layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<ImageButton
android:id="#+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#mipmap/ic_launcher_foreground" />
</LinearLayout>
This is my original theme that didn't work. It styles my TextView but ignores the ImageButton. The result is shown in the screenshot below.
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:imageButtonStyle">#style/redBackground</item>
<item name="android:textViewStyle">#style/redBackground</item>
</style>
<style name="redBackground">
<item name="android:background">#FF0000</item>
</style>
</resources>
And here's the theme that works:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="imageButtonStyle">#style/redBackground</item>
<item name="android:textViewStyle">#style/redBackground</item>
</style>
<style name="redBackground">
<item name="android:background">#FF0000</item>
</style>
</resources>
The only difference is the missing 'android:' prefix in front of the 'imageButtonStyle' attribute.
So my questions are:
What is the difference between imageButtonStyle and android:imageButtonStyle?
Why does android:textViewStyle work but not android:imageButtonStyle? They are both defined the plattforms 'attrs.xml'.
Why is there no textViewStyle (without android prefix)? Removing the prefix yields an error.
Where are the attributes defined that have no prefix? Apparently not in the plattforms 'attrs.xml'.
Where can I find proper documentation for the whole style stuff? Of course I halve already read the respective Google docs (https://developer.android.com/guide/topics/ui/look-and-feel/themes.html). But still i have basic questions like this one.
Interestingly, it seems like the 'android:imageButtonStyle' version has worked some years ago: How to apply an style to all ImageButtons in Android?. I haven't tested that myself, though.
And here's the post that proposed removing the android prefix. Including unanswered comments that ask why it works: buttonStyle not working for 22.1.1
android tag that you use is used for attribute coming from Android SDK.
app tag is used if you are using the support library.app is just a namespace for any custom parameters for a custom View.
This can be anything but if you see the root element there's probably a line xmlns:app="http://schemas.android.com/apk/res-auto" that assigns the namespace
You may also see other namespaces if you are using custom views (of your own or form a library).
In case that anyone else stumbles across the question: I've found the answer in this Droidcon talk: https://youtu.be/Jr8hJdVGHAk?t=21m12s
The topic is handled in a minute starting at 21:12.
As I understand it, specifying no namespace results in the global namespace being searched which seems to include the support libraries attributes. And indeed both, the SDK's R.attr as well as the support library's R.attr define the imageButtonStyle attribute (with slightly different descriptions). However, the support library does not define a textViewStyle attribute. So that explains why you can't omit it's android: prefix.
To answer my last question concerning the documentation: Despite the Google guide and the R.attr classes' documentation, the video mentioned above and this Google I/O talk are quite informative: https://www.youtube.com/watch?v=TIHXGwRTMWI
So the only question that is left open is why the SDK's imageButtonStyle does not work.
I am building a sample application based on latest version of Android OS..As per instructions given here I am trying to give holo:light theme to only one button in my application. How do i do it ? I have created a myStyles.xml in res/values folder but I am not able to find property to apply holo-light theme.
This is what i have in myStyles.xml file
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="mybutton" parent="android:Theme.Holo.Light">
<item name="android:background">#android:color/holo_orange_light</item>
<item name="android:textColor">#android:color/holo_blue_dark</item>
</style>
</resources>
this is i have in my activity.
<Button
android:id="#+id/button1"
style="#style/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="lol" />
I can confirm that backgroundcolor and textcolor are getting applied...(done this for testing purpose).
Currently, If i add android:theme="#android:style/Theme.Holo.Light" to AndroidManifest.xml, holo light theme is applied to entire application. However, I want this theme to be applied for only few controls ( in this case a single button control).
A theme is a style applied to an entire Activity or application, rather than an individual View.
Thus, what you are asking for is not possible. That being said, it seems odd that you would want to do this anyway. I suggest applying the holo theme to your entire app, and then customizing your Buttons only if you really need to. This is probably what the user will expect from your application.
here's my issue. I have defined custom themes and styles, so as to customize various Views, in the relevant .xml files. Here are some code extracts:
themes.xml:
...
<style name="Legacy" parent="android:Theme.NoTitleBar">
<item name="android:buttonStyle">#style/Legacy.Button</item>
...
</style>
styles.xml:
...
<style name="Legacy.Button" parent="#android:style/Widget.Button">
<item name="android:textColor">#ffffff</item>
<item name="android:background">#drawable/button_selector_blue</item>
<item name="android:textSize">15dp</item>
</style>
Let's say I set my application's theme to Legacy. If I use a Button in a layout, it will get my custom default parameters (white text, background is #drawable/button_selector_blue, etc).
Now let's say I want to keep those parameters save for the text size: I'd like to have some buttons with a larger text size, which would be defined in an titleSize attribute in attrs.xml:
...
<attr name="titleSize" format="reference|dimension" />
and which value is set for each theme in my themes.xml file.
So my layout would contain something like:
<Button
android:id="#+idmyButtonId"
android:drawableRight="#drawable/aDrawable"
android:text="#string/someText"
android:textSize="?titleSize"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</Button>
When launching my app I get the following error:
java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x2
So it seems I cannot tweak custom styles using attributes - at least not this way. Is such a thing possible ? If not, what would you use to achieve such a result ?
I'd like to give the user the ability to select among different themes, so I can't just define an additionnal ButtonWithLargeText style and directly use it in my layout.
Thanks for your help !
I finally got it to work. Instead of defining my titles' size in attrs.xml, I used dimens.xml. So now the following works:
<Button
android:id="#+idmyButtonId"
android:drawableRight="#drawable/aDrawable"
android:text="#string/someText"
android:textSize="#dimen/titleSize"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</Button>
While I get my regular text size (which I defined in my styles.xml) on the Button by using this:
<Button
android:id="#+id/idRegularButton"
android:text="#string/regularSizeText"
android:layout_width="wrap_content" android:layout_height="wrap_content">
</Button>
i have a title bar one of my project and i want to use my all screen.I think that i can do be a general( means i want a something and i will call everywhere like a style tag or theme tag) i have no idea.What can i use for?
My title bar is here:
RelativeLayout
android:layout_height="44dip"
android:layout_width="320dip"
android:background="#drawable/merhaba_header_320_44dip">
<ImageView
android:layout_height="32dip"
android:layout_width="121dip"
android:background="#drawable/merhaba_logo_121_32dip"
android:layout_centerInParent="true">
</ImageView>
<ImageView
android:layout_height="30dip"
android:layout_width="64dip"
android:background="#drawable/merhaba_btn_nedir_64_30dip"
android:layout_margin="5dip"
android:layout_alignParentRight="true">
</ImageView>
</RelativeLayout>
Hi DuyguK are you asking for a way to have a title bar that you can apply as a theme or something to all the activities in your app?
If that's so, I would recommend you to do the following.
First define a style in your res/values/styles.xml
<resources>
<style name="MyTheme" parent="android:style/Theme.Light">
<item name="android:windowTitleSize">44dip</item>
//whatever item you want/need to edit for your custom title bar
</style>
</resources>
This allows you to have a theme that is applyable to your whole app. To do this you need to go to your AndroidManifest.xml file an inside the application tag add the following:
<application android:label="#string/app_name"
android:theme="#style/MyTheme">
The android:theme tells the app to use the theme named "MyTheme" that can be found in the res/values/styles.xml file in your project.
That way you can apply correctly your custom title bar to all your activities.
Hope this answers your question if not, please specify!
An additional recommendation is to take a look at the ActionBarCompat project that comes with the samples in Android SDKs. The Android Developers page shows the project:
http://developer.android.com/resources/samples/ActionBarCompat/index.html
It has the advantage of being compatible with pre-API11 devices, is applied as a theme to your app and it is being used by lots of apps available in the store.
If you have any questions/trouble with it please tell me.
create your own style which can ofcourse extend from existing from an existing theme.
change the windowNoTitle to true.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="noTitleBarStyle" parent="android:Theme.Black">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">#color/darkGrey</item>
<item name="android:colorForeground">#ff3333</item>
</style></resources>
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.