除了ImageView和srcCompat之外,如何使用带有View的矢量drawable?

时间:2016-03-04 15:53:50

标签: android android-support-library android-vectordrawable

app:srcCompat

ImageView允许向后兼容使用矢量绘图。但除了View之外,你如何将它们与其他ImageView一起使用?例如,TextView属性,例如android:drawableLeft

同时使用矢量drawable作为android:icon MenuItem导致崩溃,但出现以下异常:

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,如何解决此问题?

9 个答案:

答案 0 :(得分:45)

更新2 :他们在支持库23.4.0中添加了再次启用它的选项:

  

对于AppCompat用户,我们添加了一个选择加入API,通过AppCompatDelegate.setCompatVectorFromResourcesEnabled()重新启用资源支持Vector Drawables(23.2中的行为) - 请记住,这仍然会导致内存问题更新配置实例的用法和问题,因此默认情况下禁用它。

<强>更新: 这不再适用于从版本23.3.0

开始
  

对于AppCompat用户,我们决定删除其中的功能   让你使用前Lollipop设备上的资源中的矢量drawables   由于版本23.2.0 / 23.2.1中的实现中发现的问题   [https://code.google.com/p/android/issues/detail?id=205236https://code.google.com/p/android/issues/detail?id=204708]。使用app:srcCompat   和setImageResource()继续工作。

来自Android Developers Google+ post

  

使用AppCompat和app:srcCompat是将矢量绘图集成到应用程序中最简单的方法。

该引用来自支持库版本23.2.0的官方blogpost

该帖子还提到了以下内容:

  

您会发现直接引用app:srcCompat之外的矢量绘图将在Lollipop之前失败。但是,AppCompat确实支持在另一个可绘制容器中引用向量drawable时加载它们,例如StateListDrawableInsetDrawableLayerDrawableLevelListDrawable和{{ 1}}。通过使用此间接,您可以在RotateDrawable的{​​{1}}属性的情况下使用向量drawable,这通常不能支持向量drawable。

这转换为以下步骤:

第1步:

创建或导入应用程序所需的矢量资源。例如,可以为搜索图标创建一个可绘制的矢量,并将其命名为TextView

第2步:

为先前创建的矢量drawable创建另一个代理可绘制资源。比方说,对于之前的android:drawableLeftic_action_search_vector.xml可以创建为简单的ic_action_search_vector.xml,其中可能包含以下行:

ic_action_search.xml

如果您从另一个可绘制资源中引用了可绘制的矢量,则可以跳过此步骤。

第3步:

使用引用向量drawable(StateListDrawable)而不是向量drawable的drawable资源(此处为<?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> )。对于菜单,它看起来像:

ic_action_search.xml

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

答案 1 :(得分:29)

对于AppCompat版本23.3.0,其中没有通过选择器XML的工作解决方案(razzledazzle接受的答案)我们可以通过编程方式执行此操作:

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

此代码与此选择器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>

更新

如果未使用API​​ 23显示矢量drawable,则需要先将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 :(得分:15)

矢量绘图可以在除app:srcCompat以外的其他地方使用前Lollipop,但需要付出代价。

我已经this diagram提供了帮助(对支持库23.4.0有效 - 至少 - 25.1.0)。

VectorDrawable cheatsheet

答案 3 :(得分:6)

您可以通过编程方式在TextView中添加Vector Drawable。利用 VectorDrawableCompat 来添加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的更多信息,请参阅此link

答案 4 :(得分:1)

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

如果您包含在您的gradle中,则情况并非如此  vectorDrawables.useSupportLibrary = true

设置为false或完全删除该行,所有向量都将按原样运行。但对于安卓版本的android,他们将能够依赖转换后的PNG

答案 5 :(得分:1)

表单android studio 3.0.0 android:src 不支持矢量图像,21以下我得到异常。使用 app:srcCompat 作为矢量图像。将所有矢量图像文件保留在 drawable 文件夹中。

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

在应用程序类中定义:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_cart_notify"/>
</layer-list>
  

现在您可以使用.xml文件了。不要忘记使用此链接: xmlns:app =&#34; http://schemas.android.com/apk/res-auto"

CREATE TRIGGER SubtractStock ON Receipt
FOR INSERT, UPDATE, DELETE
AS
UPDATE W 
SET Stock = CASE 
            WHEN WarehouseID = 'ARM01' AND I.Quantity <= Stock THEN Stock - Quantity 
            WHEN WarehouseID = 'ARM01' AND I.Quantity > Stock THEN Stock - Quantity
            WHEN WarehouseID = 'ARM02' THEN I.Quantity - Stock
        END
FROM inserted I JOIN Warehouses W ON I.ItemID = W.ItemID

现在你可以使用app:srcCompat =&#34; @ drawable / ic_cart_notify&#34;但如果你尝试在android:background或android:drawableLeft中使用,那么你得到了#34;错误的膨胀&#34;例外。为此创建一个新的包装drawable .xml文件, ic_cart_notify 是矢量图标。

{{1}}

答案 6 :(得分:0)

爸爸是对的。因此,如果您想使用带有VectorDrawables的视图选择器,则需要添加:

server/controller

到您希望在Android 5以下版本的设备上使用VectorDrawables的每个活动。

答案 7 :(得分:0)

  

在android的textview中将矢量可绘制设置为侧面可绘制

AppCompatTextView now支持app:drawableLeftCompatapp:drawableTopCompatapp:drawableRightCompatapp:drawableBottomCompatapp:drawableStartCompat和{{1 }}复合可绘制对象,支持向后移植的可绘制类型,例如 VectorDrawableCompat

将此内容添加到您的gradle文件中

app:drawableEndCompat

您可以在文本视图中使用

implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'

答案 8 :(得分:-1)

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

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

在Build.gradle文件中

 defaultConfig {

    vectorDrawables.useSupportLibrary = true
}

现在你使用像片段,活动或适配器一样使用它作为你班级的第一行

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

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