如何在Android API下21中使用矢量可绘制对象?


73

我正在开发一个Android项目,并且选择<vector>显示图标是因为它具有适应性和动态性,但是我只能在运行Android且具有API 21或更高版本的设备上运行此应用程序。我的问题是如何<vector>在较低的Android版本(例如API 14)上使用。谢谢!

<!-- drawable/ic_android_debug_bridge.xmlxml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="48dp"
android:width="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="@color/primaryColorDark"
    android:pathData="M15,9A1,1 0 0,1 14,8A1,1 0 0,1 15,7A1,1 0 0,1 16,8A1,1 `0 0,1 15,9M9,9A1,1 0 0,1 8,8A1,1 0 0,1 9,7A1,1 0 0,1 10,8A1,1 0 0,1 9,9M16.12,4.37L18.22,2.27L17.4,1.44L15.09,3.75C14.16,3.28 13.11,3 12,3C10.88,3 9.84,3.28 8.91,3.75L6.6,1.44L5.78,2.27L7.88,4.37C6.14,5.64 5,7.68 5,10V11H19V10C19,7.68 17.86,5.64 16.12,4.37M5,16C5,19.86 8.13,23 12,23A7,7 0 0,0 19,16V12H5V16Z" /></vector>`

-关于如何使用向量的实际信息stackoverflow.com/q/40678947/7045114
马克西姆Ostrovidov

Answers:


29

Vector Drawables现在向后兼容,只需将gradle版本升级到1.4.0-beta3或更高版本,然后升级IDE:

我们也很高兴为Android Studio 1.4中的矢量资产提供向后兼容性。一旦在res / drawable中具有vectorDrawable图像,Gradle插件将在构建期间自动为API级别20及以下生成栅格PNG图像。这意味着您只需要为应用程序项目更新和维护矢量资产,Android Studio就可以处理图像转换过程。

http://android-developers.blogspot.com.uy/2015/09/android-studio-14.html


51
这并非完全正确。它仅适用于imageView,其余的将在旧的Android版本上崩溃。
Android开发者

@androiddeveloper是否有解决方案,使其可用于其他视图,例如EditText和Buttons?
Red M

4
@RedM是的,但仅适用于代码(Java / kotlin)。不能使用XML(任何形式),因为它可能会导致崩溃。要通过代码获取支持库的VectorDrawable,请使用 AppCompatResources.getDrawable。请勿使用ResourcesCompatContextCompat为此。在这里阅读:stackoverflow.com/a/48237058/878126
android开发人员

93

借助23.2支持库,一直到API v7一直对Vector Drawable提供真正的支持。建议通过添加以下内容来禁用该支持的先前版本:该支持在​​构建期间呈现PNG

// Gradle Plugin 2.0+
 android {
   defaultConfig {
     vectorDrawables.useSupportLibrary = true
    }
 }

build.gradle文件。

实现非常简单。只需在Drawables上使用新的srcCompat属性即可:

<ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:srcCompat="@drawable/ic_add" />    <= this is new

在诸如TextView的drawableLeft属性的情况下,也支持Vector Drawables 。

资料来源:图书馆公告

但是,我仍然建议像Iconics库AndroidSVG或其他字体图标或SVG解决方案之类的东西来全面支持SVG标准。


4
您如何以编程方式执行此操作?
Mark13426 '16

1
如果有人使用android:drawableLeft崩溃,则可以尝试解决方法:stackoverflow.com/a/40523623/2557258
Yazon2006年

是的,我爱你。开个玩笑,这是完美的解决方案,谢谢!请注意app:srcCompat != android:srcCompat,如果您要使用此app:前缀,则必须在此处使用前缀。
马查多

91

支持库支持Lollipop之前的VectorDrawable,但使用它们的方式取决于您所拥有的支持库的版本。而且它不一定在所有情况下都有效。

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

VectorDrawable备忘单


3
这是有史以来最好的答案。
罗伯特·利伯托雷特

1
不幸的是,生成时PNG生成不支持对其他资源的引用,并且如果您android:fillColor="@color/dialog_button_text"在矢量可绘制对象中使用类似的东西,则生成PNG将会失败(因此,不包括支持库,您将花费的不仅仅是KB)。错误消息指向developer.android.com/tools/help/vector-asset-studio.html了解详细信息。
诺兰·艾米

44

我找到了解决方案!对于那些使用TextView和其他“ android”命名空间属性搜索解决方案的人。首先这是必要的:

android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }

并在应用程序类中定义以下内容:

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

现在你可以使用app:srcCompat="@drawable/ic_add",但如果您尝试使用android:background=android:drawableLeft=将崩溃的应用程序“错误坐大”的例外。

我们可以ic_add_wrapped.xml为此向量创建包装的可绘制对象:

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

现在,它可以与任何属性(例如drawableLeft或background)一起使用。刚设定android:drawableLeft="@drawable/ic_add_wrapped.xml"。警告!这是一个替代解决方案。因此,使用它需要您自担风险。


可以在所有Android版本上使用吗?即使是老的?另外,它会生成“ ic_add”作为图像吗?如果是这样,它将错过使用向量的意义。
Android开发者

@androiddeveloper它适用于所有Android版本。即使是旧的。app:srcCompat =是否将“ ic_add”生成为图像?
Yazon2006年

我问gradle文件中的标志是否将“ ic_add”生成为图像。如果可以的话,当然可以在所有Android版本上使用,但是会错过向量的要点。
Android开发人员

1
@androiddeveloper最好不要使用未完成且有错误的Android OS。
Yazon2006年

1
layer-list包装伎俩门在远程视图(通知,appwigets)无法正常工作,这是有道理的:-)。
皮埃尔·卢克(Paul-Luc Paour)

20

如果您使用android studio,则需要使用android支持库30+;如果使用Eclipse,则需要android支持库23.2.1+。

检查您的build.gradle(项目)是否使用版本2.0+在build.gradle(应用程序)中添加以下代码

// Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }

和:如果使用1.5版,请在您的build.gradle(应用程序)中添加以下内容

// Gradle Plugin 1.5  
 android {  
   defaultConfig {  
     generatedDensities = []  
  }  

  // This is handled for you by the 2.0+ Gradle Plugin  
  aaptOptions {  
    additionalParameters "--no-version-vectors"  
  }  
 }  

这是使用矢量图标的示例代码:

<ImageView  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content"  
  app:srcCompat="@drawable/ic_add"
  tools:ignore="MissingPrefix" />

要么

<ImageButton
  android:layout_width="wrap_content"
  android:background="@android:color/transparent"
  app:srcCompat="@drawable/camera"
  tools:ignore="MissingPrefix"
  android:layout_height="wrap_content"/>

在诸如TextView的情况下也支持Vector Drawable drawableLeft属性的。但是它对我来说是22+的api,但我仍然不知道如何在低api下使用。

如果您想在API 21以下兼容,也要记住:

  • 您不能android:background在xml或View.setBackgroundResource()函数中使用该属性。您需要使用View.setBackground()
  • 您不能在StateListDrawable xml-s或其他xml drawable中使用svg-s,而必须以编程方式生成它们。
  • 如果出现通知,则不能使用svg -s。

3
对于TextView,它将崩溃。
Android开发者

@androiddeveloper您在这里:stackoverflow.com/a/40523623/2557258
Yazon2006年

完整答案:)。这就是我正在寻找的。
阿舒·库玛

杜德,您已经避免了将我所有的SVG更改为PNG的出色表现,先生
dave o grady

18

当您需要以编程方式添加VectorDrawable(从SVG创建)时,可以这样进行:

icon = VectorDrawableCompat.create(resources, R.drawable.ic_map_black_24dp, null)

等等,这意味着我们可以在项目中使用SVG文件吗?不需要在IDE中将它们转换为VectorDrawable吗?
Android开发人员

当然,我们需要。这里的R.drawable.ic_map_black_24dp是SVG源转换的结果。
cVoronin

7

为了与较低版本兼容,

  1. 在gradle中添加以下内容,

    android {  
       defaultConfig {  
         vectorDrawables.useSupportLibrary = true  
        }  
     }
    
  2. 在您的应用程序类的onCreate()中添加以下代码,

    @Override
        public void onCreate() {
            super.onCreate();
            AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
        }
    
  3. 在用于imageView的xml中,

    <ImageView
        android:id="@+id/imageViewMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/transparent"
        app:srcCompat="@drawable/ic_success"/>
    
  4. 如果您要以编程方式更改图片来源,请使用此选项,

    imageView.setImageResource(R.drawable.ic_launcher);
    

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); 这有必要吗?
Akshay Shah,

EditText我想在哪里使用drawableStart呢?
普拉纳夫·卡尼克

4

我遇到了一个问题,我的矢量图像会显示出来,但是会变成全黑,这是由于无法在矢量xml文件中引用颜色资源而导致的。

因此,@color/primaryColorDark您不必使用实际的颜色,例如#212121


2

只是为了使@ 2Dee的答案完整:

VectorDrawable不能在API 20及更低版本上使用。官方方法生成png,然后变为BitmapDrawables,这打破了矢量图形的概念。

我个人更喜欢svg而不是xml向量:

  • 这样的图形可以直接从Illustrator或其他流行软件中导出
  • svg支持正确的转换,文本,遮罩和其他功能
  • 在所有平台上均可调用的真实矢量图形
  • 较小的尺寸和更快的构建

要使用矢量图形,您可以尝试https://github.com/BigBadaboom/androidsvg。它是svg阅读器和与svg兼容的ImageView。



2

您可以使用编程..to设置drawableLeft你的editTexttextView

喜欢

Drawable tick_drawable = VectorDrawableCompat.create(getResources(), R.drawable.green_tick, null);
    if (tick_drawable != null) {
        tick_drawable.setBounds(0, 0, tick_drawable.getIntrinsicWidth(),tick_drawable.getIntrinsicHeight());
    }

并像这样向左绘制。

editText.setCompoundDrawables( tick_drawable , null, null, null );

在Android 5.1上获取tick_drawable值为null
拉姆

1

在gradle默认中设置vectorDrawables.useSupportLibrary = trueAppCompatDelegate.setCompatVectorFromResourcesEnabled(true)之后在创建活动中

为了避免Textview中的android:drawableleft崩溃,请以编程方式将drawble左设置为textview,例如:

 textview.setCompoundDrawablesWithIntrinsicBounds(R.drawable.movie, 0, 0, 0);

0

我也发现了同样的问题。我做了:

vectorDrawables.useSupportLibrary = true

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

textview.setCompoundDrawablesWithIntrinsicBounds(R.drawable.movi​​e,0,0,0);

很好 但是在那之后,我得到一个错误,即找不到资源。
因此,我发现最好根据SDK版本添加矢量图像。

最终,这个解决方案对我来说是好的:-

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    textview.setCompoundDrawablesWithIntrinsicBounds(null, null, AppCompatResources.getDrawable(this, R.drawable.movie), null);
} else {
    textview.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.movie, 0);
}
  • 希望对您有所帮助。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.