I'm developing an app that has multilanguage support (using the /res/values-** way) with success. Then I want to use Holo and falling legacy devices (2.3.* for example) to use the default one (using the /res/values-v11 way).
So, I end up with a structure similar to this one (the one without language is EN, as default):
/res/values
/res/values-v11
/res/values-de
/res/values-de-v11
/res/values-es
/res/values-es-v11
... where in each one I have the following:
strings.xml
themes.xml
... where strings.xml is where the localised text are defined, and themes.xml has:
For non-v11 directories (legacy devices)
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="MyTheme" parent="#android:style/Theme">
<!-- Any customizations for your app running on pre-3.0 devices here -->
</style>
</resources>
For -v11 directories (+3.0 devices)
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="MyTheme" parent="#android:style/Theme.Holo">
<!-- Any customizations for your app running on devices with Theme.Holo here -->
</style>
</resources>
Remembering to add this attribute into the application tag on AndroidManifest.xml
android:theme ="#style/MyTheme"
This is working in all languages and all devices, current and legacy, with correct theme picking and everything. Tested in several physical devices.
So, the question:
Don't you think that this is heavily maintainable? I mean, then we have 2 string.xml files for every language which are exactly identical, but for every new text we have to fill it twice, increasing the risk of typos. The same happens if you have analytics.xml, styles.xml, ... inside
Having the language handling so nice in Android using strings.xml, is there any other workaround to have this working multitheme and multilanguage in a nicer way?
Thank you.
I'm not sure why do you need something like
values-de-v11
I would just use something like this:
values
values-de
values-fr
values-es
values-cat
...
And put inside every strings.xml file with the translation.
On the other hand you can also add the folders:
values
values-v11
And inside you can add your themes.
The folder values should have both the strings.xml for the default language (usually english) and the fallback theme file for devices without holo.
You can check all the possibilites in the documentation:
http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources
Related
I have an app that must be supported from API 8+. But I also like to have my app the holo theme for(11+). I know it won't be supported as the min sdk is 8. So the only solution will be to create 2 separate apps one for 8-11 and one for 11+. Is there any better way to do this? So that I can reduce double maintenance.
There's no need to create two separate apps. You just need to create two definitions of theme for your app:
styles.xml in /res/values-v11 (Will be used only on API 11+)
<resources>
<style name="app_theme" parent="android:Theme.Holo.Light"/>
</resources>
styles.xml in /res/values
<resources>
<style name="app_theme" parent="android:Theme.Light"/>
</resources>
and then, apply it to your application in AndroidManifest.xml:
<application
...
android:theme="#style/app_theme"
>
...
</application>
This setup uses resource qualifiers. You can read more about them here.
You can try the HoloEverywhere library to use Holo theme on Android 2.1+. It also integrates well with ActionBarSherlock.
I have a couple of app that were created with Android 1.6 and after. The problem is when I run these app on recent Android (device or simulator) like ICS, I don't have the Holo theme.
I know i can find a lot of thread on how to specify the theme but when I create a new app now, I have the new theme without any lines of code.
I don't want to have ICS theme on all android version, just ICS theme on ICS, like new holo buttons style on ICS and old grey style for older. Now I just have grey buttons for all versions.
I can create new empty projects and copy all my files into it but there must be a hidden value somewhere to chenge this.
In my manifest I have:
<uses-sdk android:minSdkVersion="3" />
<uses-sdk android:targetSdkVersion="14" />
What can be the difference between old and new created projects ?
What I'm understanding is that you want your app to switch between the legacy (classic) theme and the new Holo theme based on API version.
First, in your values (res/values) folder make a new xml. Call it styles.xml. It should contain these lines:
<resources>
<style name="AppTheme" parent="#android:style/Theme.Black"/>
</resources>
Then make a new folder in res called values-v11. In this new folder make another new xml. Also name it styles.xml This file should contain these lines:
<resources>
<style name="AppTheme" parent="#android:style/Theme.Holo"/>
</resources>
Then in your AndroidManifest.xml you Application node should contain this line:
android:theme="#style/AppTheme"
Now on devices with Honeycomb or higher you get the Holo theme and for everything else, you get the old classic theme. You can easily experiment with this to suit your needs - this is the general way to switch between themes based on API version.
Why do people use layout.xmls in their resources like:
<resources>
<item name="main" type="layout">#layout/main_twopanes</item>
</resources>
while there are folders for alternative resources to use particular XML for particular configuration?
this is called Layout Aliases link here:
To avoid this duplication of the same file for tablets and TVs (and the maintenance headache resulting from it), you can use alias files. For example, you can define the following layouts:
And add these two files:
res/values-large/layout.xml:
<resources>
<item name="main" type="layout">#layout/main_twopanes</item>
</resources>
res/values-sw600dp/layout.xml:
<resources>
<item name="main" type="layout">#layout/main_twopanes</item>
</resources>
These latter two files have identical content, but they don’t actually define the layout. They merely set up main to be an alias to main_twopanes. Since these files have large and sw600dp selectors, they are applied to tablets and TVs regardless of Android version (pre-3.2 tablets and TVs match large, and post-3.2 will match sw600dp).
I have icons for my Android menu. On Android 3+ I'm using a black ActionBar so the icons are white. However, on Android 2.x the menu is inherently white which means the icons are nearly invisible. How can I use different menu icons for different versions? I'm assuming I can do it using different drawable directories like res/drawable-mdpi-v11, but I'm wondering if there is another way so I don't have to create a bunch of different directories as I add versions or pixel densities.
EDIT: I put dark versions in res/drawable-mdpi and res/drawable-hdpi for use with Android 2.x and I put light versions in res/drawable-mdpi-v11 and res/drawable-hdpi-v11 for use with Android 3.x and higher, but my Android 2.1 (sdk 7) emulator is still showing the light version.
Any idea why?
You can Select a theme based on platform version, as outlined in the Styles and Themes dev guide. Define a style in your res/values/styles.xml like this:
<style name="ThemeSelector" parent="android:Theme.Light">
...
</style>
Then in a res/values-v11/ folder, select your theme (probably Holo, if you're dark)
<style name="ThemeSelector" parent="android:Theme.Holo">
...
</style>
Then add icons to that style. For instance, here's a snippet from the styles.xml file from the HoneycombGallery sample application.
<style name="AppTheme.Dark" parent="#android:style/Theme.Holo">
...
<item name="menuIconCamera">#drawable/ic_menu_camera_holo_dark</item>
<item name="menuIconToggle">#drawable/ic_menu_toggle_holo_dark</item>
<item name="menuIconShare">#drawable/ic_menu_share_holo_dark</item>
</style>
The bottom 3 elements are all icons in the drawable directories. You'll still need at least one folder per resolution-specific set of icons, but you can combine the light & dark icons into the same folder, but you won't have to have different folders of icons for each platform version. Also, you'll need to list them as references in the values/attrs.xml file, like this:
<resources>
<declare-styleable name="AppTheme">
<attr name="listDragShadowBackground" format="reference" />
<attr name="menuIconCamera" format="reference" />
<attr name="menuIconToggle" format="reference" />
<attr name="menuIconShare" format="reference" />
</declare-styleable>
</resources>
At which point you'll be able to refer to them within your layout XML using the "?attr/NameOfYourDrawable" dereference, like this:
<item android:id="#+id/menu_camera"
android:title="#string/camera"
android:icon="?attr/menuIconCamera"
android:showAsAction="ifRoom" />
Found on the android dev site: http://developer.android.com/guide/practices/ui_guidelines/icon_design_menu.html
Warning: Because these resources can change between platform versions, you should not reference these icons using the Android platform resource IDs (i.e. menu icons under android.R.drawable). If you want to use any icons or other internal drawable resources, you should store a local copy of those icons or drawables in your application resources, then reference the local copy from your application code. In that way, you can maintain control over the appearance of your icons, even if the system's copy changes. Note that the grid below is not intended to be complete.
/res/drawable-hdpi (for Android 2.2 and below)
/res/drawable-hdpi-v# (for Android 2.3 and above)
Have you also tried testing this on a 2.1+ phone and not an emulator? If you don't have a phone, try creating another AVD? I'm afraid that you're going to need the separate folders.
Hopefully this helps.
I tried changing the appearance of a spinner and I partly succeeded. I'm doing this via overriding parts of the theme. I managed to change the text size of the spinner item (i.e. the text size in the drop down button) with my themes.xml and styles.xml:
My themes.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomTheme" parent="#android:Theme.Holo.Light">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:spinnerItemStyle">#style/CustomSpinnerItem</item>
</style>
</resources>
My styles.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomSpinnerItem" parent="#android:Widget.TextView.SpinnerItem">
<item name="android:textAppearance">#style/CustomTextAppearance</item>
</style>
<style name="CustomTextAppearance">
<item name="android:textSize">30dp</item>
</style>
</resources>
However I cannot find the attributes that are responsible for the text appearance of the items in the dropdown list of the spinner. I tried dropDownItemStyle amongst other things. In my opinion the attribute names are not self-explanatory, so I wanted to know whether there is a documentation of what attribute does what in a style to find out which attributes to override. I found it very cumbersome to trace back all the styles used in a theme via the themes.xml and styles.xml of the platfrom and then try to find the right attributes via trial and error.
I know that one can change the appearance by passing layouts to the adapter, however, this is not really what I was looking for, since (as far as I know), you can only use inheritance in styles and not in layout xml files. If I created a custom layout for the adapter I'd have to create 9-patch images etc., which I think is a bit too time consuming in case I only want to change the text size.
Of course it's possible that I misunderstood the whole concept, since I'm new to Android ;)
You probably have found out the answer since you asked but for others looking at similar questions:
I do not know of a list of attribute names with good explanation of what they do (R.attr's page mostly gives information that is already in the name) but the way I do it is:
Start from the element I give to setDropDownViewResource(), in my case: android.R.layout.simple_spinner_dropdown_item and find.
Find its layout definition in \sdk\platforms\android-17 (specific platform version to avoid redundant results).
Get its style from the layout file. In this case: ?android:attr/spinnerDropDownItemStyle
We now have the attribute name we need.
It's better to do it that way rather than try to guess what attribute to use because you know which attribute the system itself use so it's very likely to be the correct one (unless there's a bug).
If I created a custom layout for the adapter I'd have to create
9-patch images etc.
Well, no, the layout determines what kind of GUI element you would have (a textfield, a spinner, an imagebutton, a custom element...), not how they are styled (nine-patch backgrounds, text colors...), so you still would have to mess with styles to get the right appearance.
For example, for visual consistency I ported the button, checkbox and spinner style from Theme.Holo to Gingerbread, yet I did not mess with layout, all I did was the aforementioned steps plus looking up the result (spinnerDropDownItemStyle in the above example) in themes.xml, which gave me the style name (e.g.: Widget.Holo.DropDownItem.Spinner).
Then I looked that up in styles.xml and imported it (and any parent*) in my project's styles.xml, searching and copying any Holo specific reference in my project and adjusting the namespace accordingly (add android: to attributes and replace ?android:attr with #style for what I copy to my styles.xml file).
So far I haven't had to mess with layouts at all (even the presence of radio buttons in spinner dialogs on Gingerbread is determined by an xml attribute: android:checkMark).
If a style has no parent attribute (like Widget.Holo.DropDownItem.Spinner) then its parent is the same style minus the last element (e.g.: Widget.Holo.DropDownItem)