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.
Related
I'm trying to style a TimePickerDialog for sdk 21+ (Lollipop). So far I've figured out how to change the default colorscheme in XML:
<style name="TimePickerTheme" parent="#style/Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">#ff2d6073</item> <!-- no effect -->
<item name="colorPrimaryDark">#ff2d6073</item> <!-- no effect -->
<item name="colorAccent">#ff2d6073</item>
<item name="android:textColor">#ffD0D102</item>
<item name="android:textColorPrimary">#ffD0D102</item>
</style>
This works but I'm looking for a guide or documentation for all the properties I can change.
AccentColor does the basic color scheme
TextColorPrimary does the text color
But what property, for example, do I need to change the big text in the 'header' of the dialog (where the current selected time is displayed)?
Is there some documentation that lists all the possible things you can change?
After digging through the AOSP theme and style xml files and a lot of googling I made some progress. I am now able to style most(!) things.
So this is a partial answer, not all the way there yet. But here's how far I got:
You can see that I'm now able to theme the header, the un(!)selected time part (minutes in this case), the circle, the numbers in that circle and the 'hand' (or selector). Oh, and the buttons are styled, too.
Let me explain how I got things working, first: the important thing is that you can't override things directly from you app's theme OR from a (alert)dialog theme/style. You have to go from one to the next, so to speak.
Example:
AndroidManifest.xml: Set custom theme for app and/or activity
<activity>
android:theme="#style/Theme.MyTheme"
</activity>
values-v21/styles.xml: (where your custom theme resides): set the timePickerDialogTheme
<style name="Theme.MyTheme" parent="#style/Theme.AppCompat.Light">
<item name="android:timePickerDialogTheme">#style/TimePickerDialogTheme</item>
</style>
Then below that, define the timePickerDialogTheme and set the timePickerStyle:
<style name="TimePickerDialogTheme" parent="#style/Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#ff2d6073</item> <!-- colorAccent here seems to work just fine? -->
<item name="android:timePickerStyle">#style/TimePickerDialogStyle</item>
</style>
Now you can define most of the styling here..
<style name="TimePickerDialogStyle" parent="#android:style/Widget.Material.Light.TimePicker">
<item name="colorAccent">#ff2d6073</item> <!-- colorAccent here seems to work just fine? -->
<item name="android:timePickerMode">clock</item>
<item name="android:headerBackground">#ff2d6073</item>
<item name="android:headerTimeTextAppearance">#style/TextAppearance.TimePickerDialogStyle.TimeLabel</item> <!-- TimePicker Time *TextAppearance* -->
<item name="android:numbersTextColor">#ff000000</item>
<item name="android:numbersSelectorColor">#ff2d6073</item>
<item name="android:numbersBackgroundColor">#ffdddddd</item>
</style>
The important line in the above is:
<item name="android:headerTimeTextAppearance">#style/TextAppearance.TimePickerDialogStyle.TimeLabel</item>
Because if you want to style the text (well, time, actually) in the header you need to define the headerTimeTextAppearance:
<style name="TextAppearance.TimePickerDialogStyle.TimeLabel" parent="#android:style/TextAppearance.Material">
<item name="android:textSize">60sp</item> <!-- from -->
<item name="android:textColor">#ffD0D102</item>
</style>
Now, if you take a look at the Widget.Material.TimePicker in AOSP styles.xml (ctrl-f 'timepicker' until you find it) you'll notice a bunch of other properties that you should be able to modify:
headerTimeTextAppearance
headerAmPmTextAppearance
headerSelectedTextColor
headerBackground
numbersTextColor
numbersBackgroundColor
amPmTextColor
amPmBackgroundColor
amPmSelectedBackgroundColor
numbersSelectorColor
Most of these work (as long as you prepend 'android:' for each of them) BUT I could not get 'headerSelectedTextColor' to work. I got a compile error saying something like "could not match property bla bla". Also, if you look at my example above, I hardcoded the textSize for the 'headerTimeTextAppearance' property because the '#dimen/timepicker_ampm_label_size' value threw errors.
In short: most of the things are listed above and how to get them working. But not all is clear. So I'd still see that complete documentation/guide :)
Android TimePicker material style with custom colors below, you can see http://www.zoftino.com/android-timepicker-example for TimePicker usage and styles.
<style name="MyAppThemeFour" parent="Theme.AppCompat.Light">
<item name="android:timePickerDialogTheme">#style/MyTimePickerDialogStyle</item>
</style>
<style name="MyTimePickerDialogStyle" parent="#style/ThemeOverlay.AppCompat.Dialog.Alert">
<item name="showTitle">false</item>
<item name="colorControlActivated">#ffd600</item>
<item name="colorAccent">#b71c1c</item>
<item name="android:textColorPrimary">#43a047</item>
<item name="android:textColorSecondary">#f44336</item>
</style>
When using version 1.5.0 of the Material Design Library for Android, I've found that I can get most of the theming with using this particular style:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyTimePickerTheme" parent="ThemeOverlay.MaterialComponents.TimePicker">
<item name="android:textColor">#FF121212</item>
<item name="android:textColorPrimary">#FF121212</item>
<item name="android:textColorSecondary">#FFF9F9F9</item>
<item name="colorAccent">#FF121212</item>
<item name="colorControlNormal">#FF121212</item>
<item name="colorPrimary">#FF121212</item>
<item name="colorSurface">#FFF9F9F9</item>
</style>
</resources>
This will yield in a generic - non colored - Dialog which works for white theme. For dark theme, simply invert the colors.
I've also asked here to have dynamic theming supported for this component.
Example screenshot using the above style:
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
I am trying to put padding between items in the action bar - specially my logo and the Navigation drawer icon, following is the style I am using:
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActionBarTheme" parent="#android:style/Theme.Holo.Light">
<item name="android:actionBarStyle">#style/MyActionBar</item>
</style>
<!-- ActionBar styles -->
<style name="MyActionBar" parent="#android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">#android:color/transparent</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:icon">#drawable/logo_header</item>
<item name="android:actionButtonStyle">#style/MyActionButtonStyle</item>
</style>
<style name="MyActionButtonStyle" parent="#android:style/Widget.ActionButton">
<item name="android:minWidth">32dip</item>
<item name="android:padding">12dp</item>
</style>
</resources>
However these two dont seem to work:
<item name="android:minWidth">32dip</item>
<item name="android:padding">12dp</item>
Any idea what I am missing here?
I'd make the logo into a drawable layer list instead and that way i can set its padding something like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="#drawable/my_main_icon"
android:right="20dp"/>
</layer-list>
And if you use this please update your manifest to use this drawable as the main icon instead of the current.
update: it might be better to use this icon as a logo as per reading on stackOverFlow.
so in your manifest in application tag set android:logo="my_main_icon" , researching this still.
update: if you use logo i think you have to turn it on in the actionbar...
setDisplayUseLogoEnabled() Enables the use of an alternative image (a
"logo") in the Action Bar, instead of the default application icon. A
logo is often a wider, more detailed image that represents the
application
i think the correct syntax here would be:
<item
...
android:layout_padding="12dp"
...
/>
I'm using the Android appcompat library to create a custom action bar. That all works. On devices not using the v11 theme (values folder) a bottom border does not appear as it should not. But when v11+ devices use the theme (in the values-v11 folder of course) there is a bottom border. It's a thin 1dp type border. I have a custom background applied for the actionbar and this all works on version < v11, just an annoying extra bottom border is added on v11+ devices ;-]
Now I found via another SO article where the user was using ActionBarSherlock that the base theme needed to be Theme.X and not theme.X.Light.x to resolve this issue (with no explanation as to why). I applied this same logic (I'm using android's appcompat, not sherlock one) and it worked for removing the border but then other style issues came up with radio buttons, etc, taking on the non-light theme. So I want to keep the base theme as 'Theme.AppCompat.Light' and get rid of the bottom border on the actionbar. Again, it doesn't show up on devices < v11.
Screen shots (Theme.AppCompat.Light/Theme.AppCompat):
My theme (same in values folder minus the android prefacing):
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Application theme. -->
<style name="ActionTheme" parent="#style/Theme.AppCompat.Light">
<item name="android:actionBarStyle">#style/ActionBarStyle</item>
<item name="android:windowActionBar">true</item>
</style>
<style name="ActionBarStyle" parent="#style/Widget.AppCompat.ActionBar">
<item name="android:displayOptions"></item>
<item name="android:background">#drawable/header_style</item>
<item name="android:titleTextStyle">#style/ActionBarTitleText</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:height">70dp</item>
</style>
<style name="ActionBarTitleText" parent="#style/TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">#color/color_dark_blue</item>
</style>
</resources>
Through the power of SO my question was finally answered! I tried everything the OP in the below link tried and more over the last two days. Somehow I didn't see this SO thread (I wasn't using search terms 'divider', methinks).
What worked for me was to have the no window overlay property set to null. I see that setting the window color may work on some higher version of android (4.2.x+) as well, so I decided to set both. Here is the SO link with the solution(s) to this nasty feature (bug?): link
My final values-v11/themes.xml -
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Application theme. -->
<style name="ActionTheme" parent="#style/Theme.AppCompat.Light">
<item name="android:actionBarStyle">#style/ActionBarStyle</item>
<item name="android:windowActionBar">true</item>
<item name="android:windowBackground">#android:color/white</item>
<item name="android:windowContentOverlay">#null</item>
</style>
<style name="ActionBarStyle" parent="#style/Widget.AppCompat.ActionBar">
<item name="android:displayOptions"></item>
<item name="android:background">#drawable/header_style</item>
<item name="android:titleTextStyle">#style/ActionBarTitleText</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:height">70dp</item>
</style>
<style name="ActionBarTitleText" parent="#style/TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">#color/color_dark_blue</item>
</style>
</resources>
If user2545146 answer doesn't work on lollipop.
call setElevation on the actionbar from the activity.
getSupportActionBar().setElevation(0);
The only thing that worked for me was
AppBarLayout appBarLayout = findViewById(R.id.my_app_bar_layout);
appBarLayout.setOutlineProvider(null);
api >= 21 only
I'm trying to remove the divider between the tabs in an ActionBar (actually an ActionBarSherlock) altogether; i.e. no image between tabs and no gap between the tabs either (I'm using a tiled image background in the tabs). Ideally, I'd like the dividers removed in the XML, rather than in code.
I've tried a few approaches, but nothing seems to be working, such as:
<style name="Theme.MyTheme.ActionBarTab" parent="Widget.Sherlock.ActionBar.TabBar">
<item name="android:divider">#null</item>
<item name="divider">#null</item>
<item name="actionBarDivider">#drawable/empty</item>
<item name="android:showDividers">none</item>
</style>
Turns out I was setting the wrong style. The android:showDividers attribute does work, but when it's applied to the style that inherits from the Widget.Sherlock.ActionBar.TabBar style. So the relevant bits of XML are:
<style name="Theme.Client" parent="Theme.Sherlock.Light.DarkActionBar">
<item name="android:actionBarTabBarStyle">#style/Theme.Client.ActionBarTabBar</item>
<item name="actionBarTabBarStyle">#style/Theme.Client.ActionBarTabBar</item>
</style>
<style name="Theme.Client.ActionBarTabBar" parent="Widget.Sherlock.ActionBar.TabBar">
<item name="android:background">#drawable/tab_bar_bg_tiled</item>
<item name="background">#drawable/tab_bar_bg_tiled</item>
<item name="android:showDividers">none</item>
</style>