How to set vector drawables in styles.xml - android

I am setting my icon in an ImageButton like this:
<ImageButton
style="#style/LeafPlayerMediaButton.Like"
... />
styles.xml
<style name="LeafPlayerMediaButton.Like">
<item name="android:src">#drawable/ic_app_heart_border</item>
<item name="android:contentDescription">#string/action_like</item>
</style>
#drawable/ic_app_heart_border was PNG files. However, now I upgraded to vector drawables. I know that if I set a vector drawable into an ImageView I should use app:srcCompat=#drawable/ic_app_heart_border.
While using vector drawables,if I use:
<item name="android:src">#drawable/ic_app_heart_border</item>
the app crashes for API < 21.
And if I use:
<item name="app:srcCompat">#drawable/ic_app_heart_border</item>
the app don't even start saying that app:srcCompat is not valid. What should I do?

Remove the 'app:' part of your styles.xml item.
So it'd be:
<item name="srcCompat">#drawable/ic_app_heart_border</item>
Any items with custom namespaces (anything other than 'android' and 'tools') should have their name space removed when put into styles.

Related

Drawable as styleable and how themes are selected

In this code ToolbarWidgetWrapper
I see that the Drawable is defined as styleable.
I tried to find what is that drawable and I found definitions such as:
res/res/values/themes.xml: <item name="homeAsUpIndicator">#drawable/ic_ab_back_holo_dark</item>
res/res/values/themes_holo.xml: <item name="homeAsUpIndicator">#drawable/ic_ab_back_holo_dark</item>
res/res/values/themes_holo.xml: <item name="homeAsUpIndicator">#drawable/ic_ab_back_holo_light</item>
res/res/values/themes_holo.xml: <item name="homeAsUpIndicator">#drawable/ic_ab_back_holo_dark</item>
res/res/values/styles.xml: <item name="collapseIcon">?attr/homeAsUpIndicator</item>
res/res/values/themes_material.xml: <item name="homeAsUpIndicator">#drawable/ic_ab_back_material</item>
res/res/values/themes_material.xml: <item name="homeAsUpIndicator">#drawable/ic_ab_back_material</item>
It seems that this kind of definition ensures that the icon corresponds to the app's theme and I see the icons are completely different in each definition.
Is that right? And if so, I was wondering how exactly the corresponding file is being selected? Does it depend only on some app configuration about the theme?
Is there a case that none of these would be selected?

How to set a style when using a view from imported library

I'm using this library to obtain round images. I want to create a style to control the CircularImageView view.
<style name="vircularImageView" >
<item name="android:layout_width">#dimen/cardViewImagesize</item>
<item name="android:layout_height">#dimen/cardViewImagesize</item>
<item name="app:civ_border_color">#000000</item>
</style>
The problem is the item app:civ_border_color, that gives me an error when compiling.
The attribute civ_border_color is specific for this object com.mikhaellopez.circularimageview.CircularImageView, so i'm wondering how to solve the problem.
I tried using parent but I dont' get any suggestion that matches CircularImageView.
Thank you
How can
Well, in styles you should not use any prefix for custom attributes, so it should be:
<style name="vircularImageView" >
<item name="android:layout_width">#dimen/cardViewImagesize</item>
<item name="android:layout_height">#dimen/cardViewImagesize</item>
<item name="civ_border_color">#000000</item>
</style>
Why don't you try this instead of using a big library.
RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(Activity.this.getResources(), yourbitmap);
roundedBitmapDrawable.setCircular(true);
your_imageview.setImageDrawable(roundedBitmapDrawable);

How to use textColorPrimary as background color in a style?

I want to create a style which uses the android textColorPrimary as a background color.
I tried the following which does not work, the result is my layout not beeing displayed at all.
<style name="horizontalLine">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">1dp</item>
<item name="android:background">?android:attr/textColorPrimary</item>
</style>
How do I use textColorPrimary as background color in a style?
This syntax seems to work for me, when trying to use attributes:
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="?android:textColorPrimary"
android:text="Hello"/>
(or)
<style name="MyStyle">
<item name="android:textColor">?android:textColorPrimary</item>
</style>
I can change the app theme from Holo to Holo.Light and the text color will change automatically to fit.
It doesn't work when I set it as a background of a View though - Android will crash complaining that the drawable referenced is a state list that does not specify drawables (it is a state list of colors).
Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #2: <item> tag requires a 'drawable' attribute or child tag defining a drawable
at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:178)
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:885)
at android.graphics.drawable.Drawable.createFromXml(Drawable.java:822)
at android.content.res.Resources.loadDrawable(Resources.java:1950)
... 39 more
I am using HoloEverywhere which lets me reference the resources directly, but you should get a similar problem in the native case. I don't think the primary, non-selected, non-activated (etc.) color used as a component in the state list xml is exposed through an attribute.
In any case, the text color used is dependent on the theme that you, the app developer, chooses. If you choose to use the Holo (dark) theme then your text will be a light color, and the user won't be able to affect this. You don't need to make the your line color dynamic for your app.
To apply the ?android:attr/textColorPrimary attribute as the background of a view, you have two options.
First Option
The first option is to define a shape drawable which gets its color from the ?android:attr/textColorPrimary attribute, as follows...
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="?android:attr/textColorPrimary" />
</shape>
... and, assuming you've named this drawable rectangle_shape_with_primary_text_color.xml and placed it in your application's res/drawable folder, you can set it as the background of your style as follows...
<item name="android:background">#drawable/rectangle_shape_with_primary_text_color</item>
... or set it as the background of your view directly, as follows...
android:background="#drawable/rectangle_shape_with_primary_text_color"
Second option
The second option is to set the backgroundTint property of your style or view.
You can set the backgroundTint property of your style as follows:
<style name="horizontalLine">
<item name="android:background">#android:color/white</item>
<item name="android:backgroundTint">?android:attr/textColorPrimary</item>
</style>
Or you can set the backgroundTint property of your view directly as follows:
<View
android:id="#+id/horizontalLine"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#android:color/white"
android:backgroundTint="?android:attr/textColorPrimary" />
Note that the exact value of the background property with this approach is not important but it must be set and it cannot be set to #null or #android:color/transparent.
The error message I get for this is:
org.xmlpull.v1.XmlPullParserException: Binary XML file line #18: <item> tag requires a 'drawable' attribute or child tag defining a drawable
Doing a little digging, the specs say the background attribute should support either a colour, or reference to a drawable resource:
... Looking at the resource you're referencing, it is a StateListDrawable.
platforms/android-17/data/res/color/primary_text_dark.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="#android:color/bright_foreground_dark_disabled"/>
<item android:state_window_focused="false" android:color="#android:color/bright_foreground_dark"/>
<item android:state_pressed="true" android:color="#android:color/bright_foreground_dark_inverse"/>
<item android:state_selected="true" android:color="#android:color/bright_foreground_dark_inverse"/>
<item android:state_activated="true" android:color="#android:color/bright_foreground_dark_inverse"/>
<item android:color="#android:color/bright_foreground_dark"/> <!-- not selected -->
</selector>
However, the docs for StateListDrawable also explicitly say the drawable attribute must be defined for item elements:
https://developer.android.com/guide/topics/resources/drawable-resource.html
<item>
Defines a drawable to use during certain states, as described by its attributes. Must be a child of a <selector> element.
attributes:
android:drawable
Drawable resource. Required. Reference to a drawable resource.
... which isn't the case for the case for primary_text_dark.xml. So, it's not working because the drawable you're referencing doesn't seem to conform to the spec.
I think the workaround is to reference the colour that's used in primary_text_dark for the default state: bright_foreground_dark. Seeing as that's not public, you need to go directly to the one it references, which is:
android:background="#android:color/background_light"
I take it that you want to use native android primary text color.
<item name="android:background">#android:color/primary_text_dark</item>

Change ActionBar Menu Icons depending on Style

I want to use different ActionBar Icons depending on which style I use (Dark or Light).
I couldn't figure it out how, heres what I tried:
<style name="AppThemeDark" parent="Theme.Sherlock.ForceOverflow">
<item name="android:actionButtonStyle">#style/customActionButtonStyleDark</item>
<item name="actionButtonStyle">#style/customActionButtonStyleDark</item>
</style>
<style name="AppThemeLight" parent="Theme.Sherlock.Light.ForceOverflow">
<item name="android:actionButtonStyle">#style/customActionButtonStyleLight</item>
<item name="actionButtonStyle">#style/customActionButtonStyleLight</item>
</style>
<style name="customActionButtonStyleDark" >
<item name="#drawable/action_search">#drawable/action_search</item>
</style>
<style name="customActionButtonStyleLight" >
<item name="#drawable/action_search">#drawable/action_search_light</item>
</style>
I also tried to insert <item name="#drawable/action_search">#drawable/action_search</item> directly into the theme style, but nothing worked.
Any ideas how?
Even though you found a workaround, maybe this will help someone else. I found a simple way to do this in xml (what logcat's answer is referring to). The trick I used was to create custom attributes for my menu/actionbar icons. You have to have one attribute per menu item icon.
You need to create attrs.xml in your values folder, and add your custom attributes. Think of each attribute as a constant that your themes/styles set, and then your styles/views can use those contants to set properties.
<declare-styleable name="customAttrs">
<attr name="customSearchIcon" format="reference" />
</declare-styleable>
In your styles.xml in your values folder, have your themes/styles that set your custom icon attributes to drawable references.
<style name="AppThemeDark" parent="Theme.Sherlock.ForceOverflow">
<item name="customSearchIcon">#drawable/action_search</item>
</style>
<style name="AppThemeLight" parent="Theme.Sherlock.Light.ForceOverflow">
<item name="customSearchIcon">#drawable/action_search_light</item>
</style>
Lastly, in your [menu_name].xml in your menu folder, have your menu item set its icon to your matching custom icon attribute.
<item
android:id="#+id/menuitem_search"
android:icon="?attr/customSearchIcon"/>
Now, depending on what theme is set, the icon for the menu item will change. Also, this allows you to still have API specific versions of your drawables (light and dark) using resource identifiers with your drawable folders, so you can have different menu style icons for pre 3.0 and actionbar style icons for 3.0+.
Also, remember when setting a theme at runtime (vs AndroidManifest.xml), you must set it before calling setContentView() in your Activity. It is recommended to restart your activity after changing the theme of an Activity that has already been created.
I think you did not get theming :) When you are trying to do:
<style name="customActionButtonStyleDark" >
<item name="#drawable/action_search">#drawable/action_search</item>
</style>
You are trying to overload some attribute in theme with name "#drawable/action_search"
I have bad news for you, I think there is no such. So you can go to the theme Theme.Sherlock.ForceOverflow and it's parents and see what you can overload.
If nothing help's you, and you want to have custom attribute in your theme for different icons, It's different topic. You need to create attribute in attrs.xml, point your icon source to this new attribute and define attribute value in theme. For every different button.
Solved it, but gave it up to try it with XML, I did it now programmatically:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
SharedPreferences prefs = getSharedPreferences("app", 0);
boolean isDark = "Dark".equals(prefs.getString("theme", "Dark"));
com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
// set Icons
menu.findItem(R.id.menuitem_search).setIcon(isDark ? R.drawable.action_search : R.drawable.action_search_light);
menu.findItem(R.id.menuitem_add).setIcon(isDark ? R.drawable.content_new : R.drawable.content_new_light);
menu.findItem(R.id.menuitem_share).setIcon(isDark ? R.drawable.social_share : R.drawable.social_share_light);
return true;
}
See res/xml/ic_search.xml in blog post AppCompat — Age of the vectors (Chris Barnes)
Notice the reference to ?attr/colorControlNormal
<vector xmlns:android="..."
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:pathData="..."
android:fillColor="#android:color/white"/>
</vector>

Default selector background in Clickable Views

I have some clickable views and I want to set the default available background that is present on list click (in ICS is a blue color). I have tried putting as background this:
android:background="#android:drawable/list_selector_background"
but it is not the default blue I have by default (the one I used is orange). What is the drawable used by default on android as click selector?
Thanks
This works for me:
android:background="?android:attr/selectableItemBackground"
It's list_selector_holo_dark or the equivalent holo light version; and these are the defaults in Honeycomb and above. list_selector_background is the non-holo version, used in Gingerbread and below.
EDIT: I believe (but can't confirm) that the platform agnostic selector is ?android:attr/listSelector
If you are using appcompat-v7, you can just use ?attr/selectableItemBackground.
There is a way to combine all the valid answers:
Define a attribute (eg. in values/attrs.xml):
<attr name="clickableItemBackground" format="reference"/>
In your platform dependent theme section (eg. in values/styles.xml or values/themes.xml) declare this:
<style name="Theme.Platform" parent="#android:style/Theme.Whatever">
<item name="clickableItemBackground">#android:drawable/list_selector_background</item>
</style>
In your platform dependent theme section for api-11+ (eg. in values-v11/styles.xml or values-v11/themes.xml) declare this:
<style name="Theme.Platform" parent="#android:style/Theme.Holo.Whatever">
<item name="clickableItemBackground">?android:attr/selectableItemBackground</item>
</style>
Then use ?attr/clickableItemBackground wherever needed.
A solution similar to flx's answer, but without additional attribute definition.
Platform independent style used for pre-Holo devices (in res\values\styles.xml):
<style name="SelectableItem">
<item name="android:background">#android:drawable/list_selector_background</item>
</style>
Style for Holo devices (API Level 14+) (in res\values-v14\styles.xml):
<style name="SelectableItem">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
Apply style to needed view, e.g., LinearLayout:
<LinearLayout
style="#style/SelectableItem"
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</LinearLayout>
This works fine on api 11 and above. But as noted it wont work on previous versions.
android:background="?android:attr/selectableItemBackground"
Here is a solution to have it run on all versions running android.
Add the appropriate colors within the colors.xml which is located within your values folder. It should appear as such:
<color name="white">#ffffff</color>
<color name="blue">#7ecce8</color>
Create an xml selector file. Here I named it button_selection.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#color/blue"/> <!--pressed -->
<item android:state_focused="true" android:drawable="#color/blue"/> <!-- focused -->
<item android:drawable="#color/white"/> <!-- default -->
</selector>
Go to your view or button and set the newly created button_selection.xml as its background.
android:background="#drawable/button_selection"
Alternatively,
android:background="?android:attr/listChoiceBackgroundIndicator
if you just want the items to highlight blue (or whatever the current default is) while they are clicked.
Setting Background restricts you from choosing a background color or drawable later!
So my advice is to add this style to your styles.xml:
<style name="TouchableView">
<item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>
And then on every view you only need to add:
android:theme="#style/TouchableView"
Like ANY VIEW!
<TextView
android:id="#+id/my_orders"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="0dp"
android:theme="#style/TouchableView"
android:background="#color/white"
android:gravity="left"
android:padding="10dp"
android:text="#string/my_orders"
android:textColor="#color/gray"
android:textSize="14sp" />
Don't forget to add onClickListener to see the results.
In short - android:background="?selectableItemBackground" ;)

Categories

Resources