I'd like to have two themes in my app: one with normal font size and one with smaller font size. I need to dynamically change themes in the activity's onCreate or onStart.
I've defined two themes (file themes.xml):
<style name="AppBaseTheme" parent="android:Theme.Light">
</style>
<!-- Default theme with normal font size. This one is set for the whole app in the manifest -->
<style name="NormalTheme" parent="AppBaseTheme">
<item name="android:textAppearance">#style/NormalTextSize</item>
<item name="android:textAppearanceLarge">#style/NormalTextSize.Large</item>
<item name="android:textAppearanceMedium">#style/NormalTextSize.Medium</item>
<item name="android:textAppearanceSmall">#style/NormalTextSize.Small</item>
<item name="android:editTextStyle">#style/EditText_NormalTextSize</item>
</style>
<!-- Small font size -->
<style name="SmallFontTheme" parent="NormalTheme">
<item name="android:textAppearance">#style/SmallTextSize</item>
<item name="android:textAppearanceLarge">#style/SmallTextSize.Large</item>
<item name="android:textAppearanceMedium">#style/SmallTextSize.Medium</item>
<item name="android:textAppearanceSmall">#style/SmallTextSize.Small</item>
<item name="android:editTextStyle">#style/EditText_SmallTextSize</item>
</style>
And in the file styles.xml I've defined style sets for each theme:
<!-- Normal font -->
<style name="NormalTextSize" parent="#android:style/TextAppearance">
<item name="android:textSize">16sp</item>
</style>
<style name="NormalTextSize.Large" >
<item name="android:textSize">22sp</item>
</style>
<style name="NormalTextSize.Medium" >
<item name="android:textSize">18sp</item>
</style>
<style name="NormalTextSize.Small" >
<item name="android:textSize">14sp</item>
</style>
<style name="EditText_NormalTextSize" parent="#android:style/Widget.EditText">
<item name="android:textSize">16sp</item>
</style>
<!-- Small font -->
<style name="SmallTextSize" parent="#android:style/TextAppearance">
<item name="android:textSize">14sp</item>
</style>
<style name="SmallTextSize.Large" >
<item name="android:textSize">20sp</item>
</style>
<style name="SmallTextSize.Medium" >
<item name="android:textSize">16sp</item>
</style>
<style name="SmallTextSize.Small" >
<item name="android:textSize">12sp</item>
</style>
<style name="EditText_SmallTextSize" parent="#android:style/Widget.EditText">
<item name="android:textSize">14sp</item>
</style>
To test the theme change I've created an activity and I've added two TextViews (one with textAppearanceLarge and one with textAppearanceSmall). I've also added an EditText and a list view. I haven't touched any style attribute on these views, I've kept them as they are when dropped in the layout editor. My goal is to change the theme for the whole app without having to define style or appearance for each widget.
I've also added some buttons to trigger the theme change: the new theme resource id is stored in preferences, then the activity is self-finished and a new Intent to the same test activity is launched. The activity reads the current theme setting in onCreate or onStart and calls setTheme. This theme setting change works, but only the ListView is resizing the text: the TextViews and the EditText don't resize.
So my question is what on earth have I done wrong. I've followed 3-4 tutorials and my styles are consistent with what it is supposed to work.
Notice I've only overrided text appearances in the themes because I thought that almost every text-based widget would resize based on the appearance alone (when dropped from the layout editor, every widget has an appearance). I've readed somewhere that it doesn't work that way (if so, good job guys at Google) and that you need to define text size for every kind of widget inside the themes. Well in the example above I've overrided editTextStyle and didn't work. I have also tried buttons and text views with identical result. But what puzzles me is that the ListView, which is the most complex widget on screen, is resizing correctly without defining an style for it, while the most simple widgets are not, even when defining styles for those particular kind of widgets!
The themes were ok.
The problem was the activity. You need to call setTheme before setContentView.
Kudos to #mozarty for his answer
Related
I have an Activity with a dark ActionBar. I need to remove its vertical dividers since my icons already have "built-in" dividers.
What I've tried goes below
Activity style:
<style name="sMain" parent="#android:style/Theme.Holo">
<item name="android:icon">#android:color/transparent</item>
<item name="android:actionBarStyle">#style/MyActionBar</item>
</style>
MyActionBar:
<style name="MyActionBar" parent="android:Widget.Holo.ActionBar">
<item name="android:actionBarDivider">#null</item>
</style>
This doesn't have any effect. Any ideas what I'm doing wrong?
You need to set the android:actionBarStyle attribute as part of the activity theme, not as part of the action bar style.
So I believe this should work:
<style name="sMain" parent="#android:style/Theme.Holo">
<item name="android:icon">#android:color/transparent</item>
<item name="android:actionBarStyle">#style/MyActionBar</item>
<item name="android:actionBarDivider">#null</item>
</style>
How to tell where attributes belong? I used to struggle with this too (usually solved by trial-and-error) until I discovered the use of the android.R.styleable class! Have a look here: https://developer.android.com/reference/android/R.styleable.html
If you do a search in the page for actionBarStyle you will see it shows up as Theme_actionBarStyle, meaning it is part of the Theme style (remember there is no technical difference between a theme and a style). If you do a search on ActionBar_ you will be able to iterate through all of the attributes that can be set as part of an ActionBar style.
I am using actionbar sherlock. I have an icon with transparent pixels. But when I run my app, it seems "something" is replacing these transparent pixels with the main background from the theme, not the actionbar background.
It does not matter if the main background is specified as a #color or a #drawable (9 patch) but in the latter case (which is what I actually want) there is an additional quirk in that a few pixels of the main background 9 patch appear at the right(!) hand edge of the actionbar. Go figure.
I have no idea what's going on here. Just that if I remove the background items from the main style, the actionbar looks as it should (so that seems to be the problem).
Has anyone else seen such behaviour before? Thanks for taking a look!
I'll paste my style.xml below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ViewPagerIndicator">
<attr name="vpiSubTabPageIndicatorStyle" format="reference"/>
</declare-styleable>
<style name="Theme.StandBy" parent="Theme.Sherlock.Light.DarkActionBar">
<item name="vpiTabPageIndicatorStyle">#style/CustomTabPageIndicator</item>
<item name="vpiSubTabPageIndicatorStyle">#style/CustomSubTabPageIndicator</item>
<item name="android:actionBarStyle">#style/Theme.StandBy.App.ActionBar</item>
<item name="actionBarStyle">#style/Theme.StandBy.App.ActionBar</item>
<!-- ------------------------------------------ ->
<!-- I tried both of these, but can't get transparent pixels in my icon to work --->
<!-- when I use the 9 patch (frg_background) in stead of a plain color, there -->
<!-- are extra artefacts in that some of the 9 patch pixels end up on the righthand -->
<!-- side of the action bar -->
<!--<item name="android:background">#drawable/frg_background</item>
<item name="background">#drawable/frg_background</item>-->
<item name="android:background">#color/cream</item>
<item name="background">#color/cream</item>
<!-- ------------------------------------------ ->
</style>
<style name="Theme.StandBySubTab" parent="Theme.Sherlock.Light.DarkActionBar">
<item name="vpiTabPageIndicatorStyle">#style/CustomSubTabPageIndicator</item>
</style>
<style name="Theme.StandBy.App.ActionBar" parent="Widget.Sherlock.ActionBar">
<!--
Both `android:xyz` and `xyz` need to be set to support 4.x and 2.x devices.
-->
<item name="android:displayOptions">showHome</item>
<item name="displayOptions">showHome</item>
<item name="android:background">#drawable/bar</item>
<item name="background">#drawable/bar</item>
</style>
<!-- top tab style -->
<style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
<item name="android:background">#drawable/tab_background</item>
<item name="android:textAppearance">#style/CustomTabPageIndicator.Text</item>
<item name="android:divider">#drawable/tab_divider</item>
<item name="android:showDividers">middle</item>
<item name="android:paddingLeft">4dp</item>
<item name="android:paddingRight">4dp</item>
</style>
<style name="CustomTabPageIndicator.Text">
<item name="android:textColor">#color/tab_text</item>
<item name="android:textSize">10sp</item>
<item name="android:textStyle">bold</item>
</style>
<!-- sub tab style -->
<style name="CustomSubTabPageIndicator" parent="Widget.TabPageIndicator">
<item name="android:background">#drawable/sub_background</item>
<item name="android:textAppearance">#style/CustomSubTabPageIndicator.Text</item>
<item name="android:paddingLeft">4dp</item>
<item name="android:paddingRight">4dp</item>
</style>
<style name="CustomSubTabPageIndicator.Text">
<item name="android:textColor">#color/sub_text</item>
<item name="android:textSize">10sp</item>
<item name="android:textStyle">bold</item>
</style>
</resources>
EDIT: since the problem goes away if I do not specify background and android:background in my main style (Theme.StandBy) it occurred to me I might be asking the wrong question. My purpose in putting these items in is to specify a default background for all of my fragments (content of tabs). That works, but has the unwanted side-effects I mentioned above. Should I be doing this in another way? Thanks for any suggestions!
Properties that you set on the theme will be inherited by EVERY view when the view resolves its styles. In your case, every view that doesn't have an explicit background set somewhere else will render an #color/cream background. This is bound to cause the kinds of visual problems you're experiencing, as well as creating massive amounts of unnecessary overdraw.
A much better way to apply common styling to your fragments is to simply create a style
<style name="Fragment">
<item name="android:background">#color/cream</item>
</style>
and reference it from the root view of each fragment, e.g.
<LinearLayout style="#style/Fragment">
...
</LinearLayout>
This means a bit of extra typing as the reference to the style needs to go into each fragment, but there is no good way to avoid this -- Conceptually only View classes can have their own default style set by the theme (e.g. you can point the textViewStyle attribute at a style definition, and it will apply to all TextViews). However Fragments (or Activities for that matter) aren't Views, so this mechanism doesn't apply.
In my Android app, I am using various custom themes in different activities, all of which work fine. All these themes use the same custom styles for buttons, edit controls etc.
My preferences use standard Preference activities, which I define in XML and style via the manifest.
However, when I have a preference that causes an alert dialog to get launched, for example a ListPreference, the dialog uses the standard buttons. It does seem to use my custom EditText style in the EditTextPreference... but not my background or text colour.
Anyone have any idea why this is happening ?
Some of the code:
Styles:
<style name="Theme.Prefs" parent="#android:style/Theme.Holo.Light">
<item name="android:windowBackground">#drawable/background</item>
<item name="android:buttonStyle">#style/CustomButtonStyle</item>
<item name="android:editTextStyle">#style/CustomEditTextStyle</item>
</style>
<style name="CustomButtonStyle" parent="#android:style/Widget.Holo.Button">
<item name="android:background">#drawable/custom_button</item>
<item name="android:textSize">#dimen/dialog_text_size_normal</item>
<item name="android:textColor">#color/dialog_control_colour</item>
</style>
<style name="CustomEditTextStyle" parent="#android:style/Widget.Holo.EditText">
<item name="android:background">#drawable/custom_textfield</item>
<item name="android:textColor">#color/dialog_control_colour</item>
<item name="android:textSize">#dimen/dialog_text_size_normal</item>
</style>
And in the manifest:
<activity
android:name="com.breadbun.prefs.MainPreferencesActivity"
android:theme="#style/Theme.Prefs"
android:screenOrientation="portrait">
</activity>
To customize the alertDialog you need to add the second row to your main theme, and then customize the DialogStyle the way you want it.
<style name="AppTheme" parent="android:Theme.Material">
<item name="android:alertDialogTheme">#style/DialogStyle</item>
</style>
<style name="DialogStyle" parent="android:Theme.Material.Dialog.Alert">
</style>
I need to find what style/theme is used by the webview for the view that pops when the user clicks a combo box in the html page.
On certain phones, the text gets chopped and I need to reduce the text size or allow each line to span multiple lines.
I have tried 5 styles so far, without success:
<style name="teststyle1" parent="#android:style/Widget.DropDownItem.Spinner">
<item name="android:singleLine">false</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#FF00FF</item>
<item name="android:checkMark">#drawable/another_btn_radio</item>
</style>
<style name="teststyle2" parent="#android:style/Widget.TextView.SpinnerItem">
<item name="android:singleLine">false</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#FF00FF</item>
<item name="android:checkMark">#drawable/another_btn_radio</item>
</style>
<style name="teststyle3" parent="#android:style/Widget.DropDownItem">
<item name="android:singleLine">false</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#FF00FF</item>
<item name="android:checkMark">#drawable/another_btn_radio</item>
</style>
<style name="teststyle4" parent="#android:style/Widget.Spinner">
<item name="android:singleLine">false</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#FF00FF</item>
<item name="android:checkMark">#drawable/another_btn_radio</item>
</style>
<style name="teststyle5" parent="#android:style/Widget.Spinner">
<item name="android:singleLine">false</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#FF00FF</item>
<item name="android:checkMark">#drawable/another_btn_radio</item>
</style>
Any help would be greatly appreciated.
Allow Multiple lines would be better.
If you only set the size.
It would be changed if you want to add some words sometime.
This change is actually going to be done on the HTML side of things not in android. Use the webkit-appearance CSS tag to specify an appearance style then you can work with the wrapping using CSS.
URL: http://css-infos.net/property/-webkit-appearance
Look at AndroidManifest.xml at the <activity> tag for whichever activity those screens are from. Under the android:theme property is where you set the theme, or in this case find out what the current one is! It looks like it might be Theme.Dark but I'm not sure off the top of my head
Or if you're just trying to change the list items in that view to fit the title, a change of font size is all you need. You can set it in the layout or programmatically in the Activity with:
TextView view = (TextView) findViewById('R.id.your_view');
view.setTextSize(12);
// ^^^ will set font size to 12dp, you can use 'setTextSize(pt,12)' for different units
I'd look at AndroidManifest.xml and look at the activity's theme, it looks like it's a system styling. Source:
http://developer.android.com/guide/topics/ui/themes.html
More Links to look at
Set spinner within custom dialog
Android: Where is the Spinner widget's text color attribute hiding?
Android - Customizing the Spinner widget Look and Feel
Another Stab At This
Is this project on Github? Could you post your logic for the registration view?
I want to overload how an android Button looks, except I want to overload only one attribute i.e. the android:background. I know I could write something like:
<style name="App_TextButtonStyle" parent="???">
<item name="android:background">#drawable/filled_roundededges_nostroke</item>
</style>
Where parent="???" specifies which style I inherit from. My question is which style should I inherit from do that I get everything from the android default style for buttons and just define a new background.
I have used style for buttons without specifying "parent" attribute
<style name="BigButtonStyle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:background">#drawable/backbutton</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">8pt</item>
<item name="android:textStyle">bold</item>
<item name="android:layout_margin">10pt</item>
</style>
I think it could be enough for you to define your style without "parent".
This is mostly for future visitors, I found a solution to the problem:
<style name="App_TextButtonStyle" parent="#android:style/Widget.Button">
<item name="android:background">#drawable/filled_roundededges_nostroke</item>
</style>
#android:style/Widget.Button references the default style of the button in the currently selected theme. You could also use the holo widget button style #android:style/Widget.Holo.Button (available since api 11).
You might want to look in <android-sdk-install-folder>/platforms/android-XX/data/res/values for the files styles.xml and themes.xml to check out all styles android uses for a given platform version.