如何使用vector绘图与除了ImageView与srcCompat?
使用ImageView
app:srcCompat
允许向后兼容使用vector绘图。 但是,除了ImageView
你怎样才能使用它们呢? 例如,像android:drawableLeft
这样的TextView
属性。
同样使用带有MenuItem
的android: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
支持在另一个可绘制容器(如StateListDrawable
,InsetDrawable
,LayerDrawable
,LevelListDrawable
和RotateDrawable
中引用它们时加载vectorRotateDrawable
。 通过使用这种间接方式,可以在TextView
的android: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)。
您可以以编程方式在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));