41

app:srcCompatwithImageView允许向后兼容使用矢量可绘制对象。但是你怎么能把它们和其他Views一起使用ImageView呢?例如,TextViewandroid:drawableLeft.

同样使用可绘制矢量作为android:iconwithMenuItem会导致崩溃,但有以下异常:

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

4

9 回答 9

45

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

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

更新:这不再适用于版本 23.3.0

对于 AppCompat 用户,由于版本 23.2.0/23.2.1 [ https://code.google.com com/p/android/issues/detail?id=205236https://code.google.com/p/android/issues/detail?id=204708]。使用 app:srcCompat 和 setImageResource() 继续工作。

来自Android 开发者 Google+ 帖子


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

该引用来自支持库版本 23.2.0 发布的官方博客文章。

该帖子还提到以下内容:

app:srcCompat你会发现在 Lollipop 之前直接引用矢量 drawable会失败。但是,AppCompat当向量可绘制对象在另一个可绘制容器(例如 、 、 、 和 )中被引用时StateListDrawableInsetDrawable确实LayerDrawable支持LevelListDrawable加载它们RotateDrawable。通过使用这种间接方式,您可以在诸如TextView'android:drawableLeft属性之类的情况下使用矢量可绘制对象,这通常无法支持矢量可绘制对象。

这转化为以下步骤:

步骤1:

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

第2步:

为之前创建的矢量可绘制对象创建另一个代理可绘制资源。比如说,对于前面的ic_action_search_vector.xmlic_action_search.xml可以创建为一个简单的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>

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

第 3 步:

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

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

这是解决该问题的方法!

于 2016-03-04T15:53:49.783 回答
31

对于 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 未显示矢量可绘制对象,则需要先将其转换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());
}
于 2016-04-21T07:33:39.180 回答
18

Vector drawables可以在Lollipop之前在其他地方使用app:srcCompat,但它是有代价的。

我已制作此图以提供帮助(对支持库 23.4.0 至 - 至少 - 25.1.0 有效)。

VectorDrawable 备忘单

于 2017-01-25T17:16:51.963 回答
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 的更多信息,请参阅此 链接

于 2016-11-29T10:39:32.440 回答
1

Form android studio 3.0.0 android:src不支持矢量图像,低于 21 我得到异常。使用app:srcCompat作为矢量图像。将所有矢量图像文件保存在可绘制文件夹中。

android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }

在应用程序类中定义这个:

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

现在您可以使用您的 .xml 文件了。不要忘记使用此链接: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>

现在您可以使用 app:srcCompat="@drawable/ic_cart_notify" 但如果您尝试在 android:background 或 android:drawableLeft 中使用,则会出现“充气错误”异常。为此创建一个新的包装可绘制 .xml 文件,ic_cart_notify是矢量图标。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_cart_notify"/>
</layer-list>
于 2017-12-31T04:54:56.310 回答
1

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

如果您在 gradle 中包含 vectorDrawables.useSupportLibrary = true,则这不是真的

设置为 false 或完全删除该行,您的所有向量都将照常工作。但是对于旧版本的android,他们将能够依赖转换后的PNG

于 2016-09-07T14:49:26.300 回答
0

大豆是对的。因此,如果您想将选择器用于带有 VectorDrawables 的视图,您需要添加:

    static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(trfor);
}

到您想在 Android 5 以下版本的设备上使用 VectorDrawables 的每个 Activity。

于 2018-01-09T12:24:02.737 回答
0

在android的textview中将vector drawable设置为side drawable

AppCompatTextView 现在支持app:drawableLeftCompatapp:drawableTopCompatapp:drawableRightCompatapp:drawableBottomCompat和复合可绘制对象,支持向后移植的可绘制类型app:drawableStartCompatapp:drawableEndCompat例如VectorDrawableCompat

将此包含在您的 gradle 文件中

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

在您的文本视图中,您可以使用

app:drawableLeftCompat
app:drawableStartCompat
于 2019-01-15T08:56:44.850 回答
-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" />

东西.java

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

或者如果您需要动态设置可绘制 ID

thumbIcon.setImageDrawable(ContextCompat.getDrawable(context,drawableID));
于 2017-02-16T18:20:36.107 回答