How to use vector drawings with a view besides ImageView with srcCompat?

app:srcCompat with ImageView allows backward compatible use of vector drawings. But how can you use them with other View besides ImageView ? For example, TextView attributes such as android:drawableLeft .

Also, using a vector output as android:icon with MenuItem failed with the following exception:

 Fatal Exception: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown> at android.view.LayoutInflater.createView(LayoutInflater.java:626) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702) at android.view.LayoutInflater.inflate(LayoutInflater.java:470) at android.view.LayoutInflater.inflate(LayoutInflater.java:398) at android.support.v7.view.menu.MenuItemImpl.setActionView(MenuItemImpl.java:621) at android.support.v7.view.menu.MenuItemImpl.setActionView(MenuItemImpl.java:40) at android.support.v4.view.MenuItemCompat.setActionView(MenuItemCompat.java:310) at android.support.v7.view.SupportMenuInflater$MenuState.setItem(SupportMenuInflater.java:465) at android.support.v7.view.SupportMenuInflater$MenuState.addItem(SupportMenuInflater.java:479) at android.support.v7.view.SupportMenuInflater.parseMenu(SupportMenuInflater.java:196) at android.support.v7.view.SupportMenuInflater.inflate(SupportMenuInflater.java:118) at com.example.niceapp.context.main.MainActivity.onCreateOptionsMenu(MainActivity.java:101) at android.app.Activity.onCreatePanelMenu(Activity.java:2578) 

With library support 23.2.0, how to solve this problem?

+34
android android-support-library android-vectordrawable
Mar 04 '16 at 15:53
source share
7 answers

For AppCompat version 23.3.0, where there is no solution for working with the XML selector (accepted razzledazzle answer), we can do this programmatically:

activity_main.xml

 <android.support.v7.widget.AppCompatImageButton android:id="@+id/btnEnter" /> 

MainActivity.java

 AppCompatImageButton image = (AppCompatImageButton) findViewById(R.id.btnEnter); if (image != null) { VectorDrawableCompat vcAccept = VectorDrawableCompat.create(getResources(), R.drawable.vc_accept, getTheme()); VectorDrawableCompat vcAcceptWhite = VectorDrawableCompat.create(getResources(), R.drawable.vc_accept_white, getTheme()); StateListDrawable stateList = new StateListDrawable(); stateList.addState(new int[]{android.R.attr.state_focused, -android.R.attr.state_pressed}, vcAccept); stateList.addState(new int[]{android.R.attr.state_focused, android.R.attr.state_pressed}, vcAcceptWhite); stateList.addState(new int[]{-android.R.attr.state_focused, android.R.attr.state_pressed}, vcAcceptWhite); stateList.addState(new int[]{}, vcAccept); image.setImageDrawable(stateList); } 

This code is equivalent for this xml selector:

 <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/vc_accept" /> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/vc_accept_white" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/vc_accept_white" /> <item android:drawable="@drawable/vc_accept" /> </selector> 



UPDATE

If a vector drawing is not shown using API 23, you need to first convert VectorDrawable to regular Drawable . If you want to use setCompoundDrawablesWithIntrinsicBounds you need to do this, but for StateListDrawable I did not need to.

 Drawable icon; if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { icon = VectorDrawableCompat.create(getResources(), R.drawable.vc_icon, getContext().getTheme()); } else { icon = getResources().getDrawable(R.drawable.vc_icon, getContext().getTheme()); } 
+25
Apr 21 '16 at 7:33
source share

Update 2 : they added the ability to enable it again in the 23.4.0 support library:

For AppCompat users, we have added an API to re-enable support for vector drawings from resources (the behavior found in 23.2) using AppCompatDelegate.setCompatVectorFromResourcesEnabled () - keep in mind that this may still cause memory problems and update problems instances of Configuration, so why is it disabled by default.

Update : This no longer works since version 23.3.0

For AppCompat users, we decided to remove features that allow the use of vector drawings from resources on devices prior to Lollipop due to problems found during implementation in version 23.2.0 / 23.2.1 [ https://code.google.com/p/ android / issues / detail? id = 205236 , https://code.google.com/p/android/issues/detail?id=204708] . Using the application: srcCompat and setImageResource () continues to work.

From the announcement of Google+ developers on Google+




Using AppCompat and the application: srcCompat is the most reliable way to integrate vector drawings into your application.

This quote is from the official blogpost for the release of version 23.2.0 in the Support Library.

The message also mentions the following:

You will find direct access to vector drawings outside the app:srcCompat , which will not run until Lollipop. However, AppCompat supports loading vector vectors when they are referenced in another container, such as StateListDrawable , InsetDrawable , LayerDrawable , LevelListDrawable and RotateDrawable . Using this indirection, you can use vector drawings in cases such as the TextView s android:drawableLeft , which normally cannot support vector drawings.

This leads to the following steps:

Step 1:

Create or import the vector resource that you need for the application. For example, you can create a vector that ic_action_search_vector.xml search icon and name it ic_action_search_vector.xml

Step 2:

Create another resource that can be used for the proxy server for the previously created vector. Let's say for the previous ic_action_search_vector.xml , ic_action_search.xml can be created as a simple StateListDrawable , which can contain the following lines:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/ic_action_search_vector"/> </selector> 

You can skip this step if you specified a vector that can be extracted from another resource that you will use with your view.

Step 3:

Use a resource that can be pulled out (here, ic_action_search.xml ), which refers to a vector drawable ( ic_action_search_vector.xml ) instead of directly converting a vector. For the menu, it will look like this:

 <item android:id="@+id/search" android:title="@string/search" android:icon="@drawable/ic_action_search" app:showAsAction="always"/> 

This is the solution to this problem!

+45
Mar 04 '16 at 15:53
source share

vector images can be used pre-Lollipop in places other than app:srcCompat , but it comes with a price.

I made this diagram to help (valid for support library 23.4.0 - at least - 25.1.0).

VectorDrawable cheatsheet

+11
Jan 25 '17 at 17:16
source share

You can add Vector Drawable to TextView programmatically. Use VectorDrawableCompat to add drawableLeft / drawableRight / drawableTop / drawableBottom / drawableStart / drawableEnd.

Steps:

I am. If the TextView is inside an Activity:

 TextView tvUserName= (TextView)findViewById(R.id.et_username_or_email); VectorDrawableCompat drawableCompat=VectorDrawableCompat.create(getResources(), R.drawable.layer_list_ic_user, tvUserName.getContext().getTheme()); tvUserName.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableCompat, null, null, null); 

II. If the TextView is inside the fragment:

 TextView tvUserName= (TextView )view.findViewById(R.id.et_username_or_email); VectorDrawableCompat drawableCompat=VectorDrawableCompat.create(getActivity().getResources(), R.drawable.layer_list_ic_user, tvUserName.getContext().getTheme()); tvUserName.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableCompat, null, null, null); 

For more information about VectorDrawableCompat see link

+5
Nov 29 '16 at 10:39
source share

Android 5.0 (API level 21) and above provides vector support. If your application has a minimum API level that is lower, Vector Asset Studio adds a vector file for drawing to your project; also, during build, Gradle creates PNG bitmaps with various resolutions. Gradle generates PNG densities defined by the generated Domain Properties (DSL) property created in the build.gradle file. To create PNG for the build system, you need Android Plugin for Gradle 1.5.0 or later.

This is not true if you included vectorDrawables.useSupportLibrary = true in your gradle

either set the value to false, or completely delete the line, and all your vectors will work the way they were. But for older versions of android, they will be able to rely on converted PNG

+1
Sep 07 '16 at 14:49
source share

I am using the new support library, and all I need to do is:

 compile 'com.android.support:appcompat-v7:25.1.1' 

In the Build.gradle file

  defaultConfig { vectorDrawables.useSupportLibrary = true } 

Now when you use the same fragment, activity or adapter, use this as the first line in your class

 static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

after that use, as before, something.xml

 <ImageView android:id="@+id/ivMainNavigationIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" /> 

Something.java

 thumbIcon.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.ic_check_circle_black_24dp)); 

or if you have the required id for dynamic dialing

 thumbIcon.setImageDrawable(ContextCompat.getDrawable(context,drawableID)); 
0
Feb 16 '17 at 18:20
source share

The android studio 3.0.0 form android : src does not support a vector image and below 21 is my exception exception. use app: srcCompat for vector image. Store the vector image files inside the drawable folder.

 android { defaultConfig { vectorDrawables.useSupportLibrary = true } } 

And in the application class, define this:

 @Override public void onCreate() { super.onCreate(); AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

Now you can use your .xml file. Be sure to include this link: xmlns: app = "http://schemas.android.com/apk/res-auto"

 <RelativeLayout android:id="@+id/counterValuePanel" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/ic_cart_notify"/> </RelativeLayout> 

Now you can use the application: srcCompat = "@ drawable / ic_cart_notify", but if you try to use in android: background or android: drawableLeft, then you have an exception "Bloat error". To do this, create a new wrapped .xml file, ic_cart_notify - vector icon.

 <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/ic_cart_notify"/> </layer-list> 
0
Dec 31 '17 at 4:54 on
source share



All Articles