如何使用vector绘图与除了ImageView与srcCompat?

使用ImageView app:srcCompat允许向后兼容使用vector绘图。 但是,除了ImageView你怎样才能使用它们呢? 例如,像android:drawableLeft这样的TextView属性。

同样使用带有MenuItemandroid:icon作为vectordrawable会导致崩溃,但有以下例外情况:

 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) 

通过支持库23.2.0,如何解决这个问题?

对于通过select器XML(razzledazzle接受的答案)没有工作解决scheme的AppCompat版本23.3.0,我们可以通过编程方式来完成:

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); } 

这个代码对于这个select器是等效的xml:

 <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

如果vector绘制不使用API​​ 23显示,则需要VectorDrawable转换为常规的Drawable 。 如果你想使用setCompoundDrawablesWithIntrinsicBounds你需要这样做,但对于StateListDrawable我不需要。

 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()); } 

更新2 :他们添加了一个选项来在Support Library 23.4.0中再次启用它:

对于AppCompat用户,我们已经添加了一个select性的API来通过AppCompatDelegate.setCompatVectorFromResourcesEnabled()从资源(23.2中的行为)重新启用支持Vector Drawables – 请记住,这仍然可能导致内存使用和问题更新configuration实例,因此为什么它默认是禁用的。

更新 :从版本23.3.0开始,这不再起作用

对于AppCompat用户,我们已经决定删除​​允许您使用棒棒糖前设备资源中的vector绘图的function,因为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 ] 。 使用app:srcCompat和setImageResource()继续工作。

来自Android开发者Google+的post


使用AppCompat和应用程序:srcCompat是将vector绘图集成到您的应用程序的最简单的方法。

这个引用来自Support Library 23.2.0版的官方博客 。

这个post还提到了以下几点:

你会发现在app:srcCompat之外直接引用vector绘图app:srcCompat在Lollipop之前将会失败。 但是, AppCompat支持在另一个可绘制容器(如StateListDrawableInsetDrawableLayerDrawableLevelListDrawableRotateDrawable中引用它们时加载vectorRotateDrawable 。 通过使用这种间接方式,可以在TextViewandroid:drawableLeft属性等情况下使用vector绘图,这通常不能支持vector绘图。

这转换成以下步骤:

步骤1:

创build或导入您需要的应​​用程序的vector资源。 例如,可以为search图标创build一个vector绘图,并将其命名为ic_action_search_vector.xml

第2步:

为以前创build的vector绘制创build另一个代理可绘制资源。 比如,对于之前的ic_action_search_vector.xml ,可以将ic_action_search.xml创build为一个简单的StateListDrawable ,它可以包含以下StateListDrawable行:

 <?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> 

如果您从另一个可视资源引用可绘制的vector,则可以跳过此步骤,您将使用该资源。

第3步:

使用引用vector绘制( ic_action_search_vector.xml )的可绘制资源(此处为ic_action_search.xml ),而不是直接绘制vector。 对于菜单,它看起来像:

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

这是解决这个问题的方法!

vector绘制可以使用之前的棒棒糖比其他地方比app:srcCompat ,但它带有一个价格。

我已经使这个图帮助(有效的支持库23.4.0至less – 25.1.0)。

VectorDrawable作弊表

您可以以编程方式在TextView中添加Vector Drawable。 使用VectorDrawableCompat inorder来添加drawableLeft / drawableRight / drawableTop / drawableBottom / drawableStart / drawableEnd。

脚步:

一世。 如果TextView在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。 如果TextView在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); 

有关VectorDrawableCompat的更多信息请参阅此链接

Android 5.0(API级别21)及更高版本提供了vector绘图支持。 如果您的应用程序的最低API级别较低,则Vector Asset Studio会将vector可绘制文件添加到您的项目; 另外,在构build时,Gradle会创build各种分辨率的PNG栅格图像。 Gradle生成由build.gradle文件中的域特定语言(DSL)generatedDensities属性指定的PNG密度。 要生成PNG,构build系统需要Android Plugin for Gradle 1.5.0或更高版本。

如果你在你的gradle中包含vectorDrawables.useSupportLibrary = true,那么这是不正确的

要么设置为false或完全删除线,所有的载体将按原样运行。 但对于Android的老版本,他们将能够依靠转换的PNG

我正在使用新的支持库,我所要做的就是:

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

在Build.gradle文件中

  defaultConfig { vectorDrawables.useSupportLibrary = true } 

现在,当你在使用片段,活动或适配器的时候,将它用作你class级的第一行

 static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

之后就像我们以前那样使用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)); 

或者如果你有可绘制的ID需要dynamic设置

 thumbIcon.setImageDrawable(ContextCompat.getDrawable(context,drawableID));