【问题标题】:How to use VectorDrawables in Android API lower than 21?如何在低于 21 的 Android API 中使用 VectorDrawables?
【发布时间】:2016-03-28 20:03:27
【问题描述】:

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

<!-- drawable/ic_android_debug_bridge.xml -->
<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>

【问题讨论】:

标签: java android svg android-vectordrawable


【解决方案1】:

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

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

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

【讨论】:

  • 这并不完全正确。它只适用于 imageView,其余的它会在旧的 Android 版本上崩溃。
  • @androiddeveloper 是否有解决方案使其适用于 EditText 和 Buttons 等其他视图?
  • @RedM 是的,但仅限于代码 (Java/kotlin)。不在 XML(任何类型)中,因为它可能会导致崩溃。要通过代码获取支持库的 VectorDrawable,请使用 AppCompatResources.getDrawable 。不要使用ResourcesCompatContextCompat。在这里阅读:stackoverflow.com/a/48237058/878126
【解决方案2】:

只是为了让@2Dee 的回答完整:

VectorDrawable 不能用于 API 20 及更低版本。官方方法生成png,然后变成BitmapDrawables,打破了矢量图的思路。

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

  • 此类图形可以直接从 Illustrator 或其他流行软件中导出
  • svg 正确支持转换、文本、蒙版和其他内容
  • 所有平台上的真正可缩放矢量图形
  • 体积更小,构建速度更快

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

【讨论】:

    【解决方案3】:

    使用支持库 23.2,一直到 API v7 都提供了对 Vector Drawables 的真正支持。 建议禁用以前版本的支持,它在构建时呈现 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 属性等情况下也支持矢量可绘制对象。

    来源:library announcement

    但是,我仍然建议使用 Iconics libraryAndroidSVG 或其他字体图标或 SVG 解决方案来获得完整的 SVG 标准矢量支持。

    【讨论】:

    • 你如何以编程方式做到这一点?
    • 如果有人使用 android:drawableLeft 崩溃,您可以尝试解决方法:stackoverflow.com/a/40523623/2557258
    • 是的,我爱你。开个玩笑,这是完美的解决方案,谢谢!如果你要使用这个请注意app:srcCompat != android:srcCompat,你必须在这里使用app:前缀。
    【解决方案4】:

    如果你使用 android studio,你需要使用 android Support Repository 30+ 如果使用 Eclipse,则需要 android 支持库 23.2.1+。

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

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

    并且:如果使用 1.5 版,请在您的 build.gradle(app) 中添加以下内容

    // 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 的 drawableLeft 属性等情况下也支持矢量可绘制对象。但它对我来说 api 22+ 有效,但我仍然不知道它如何适用于低 api。

    如果您想兼容 API 21 以下,请注意:

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

    【讨论】:

    • TextView 会崩溃。
    • @androiddeveloper 你在这里:stackoverflow.com/a/40523623/2557258
    • 完整答案:)。这就是我要找的。​​span>
    • 老兄,你把我所有的 SVG 都改成 PNG 做得好,先生
    【解决方案5】:

    我找到了解决方案!对于那些使用 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=,它将导致应用程序崩溃并出现“错误充气”异常。

    我们可以为这个向量创建包装的drawable 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”生成为图像?如果是这样,它就错过了使用向量的意义。
    • @androiddeveloper 它适用于所有 Android 版本。甚至是旧的。 app:srcCompat= 是否将“ic_add”生成为图像?
    • 我询问了 gradle 文件中的标志是否将“ic_add”生成为图像。如果是这样,当然它适用于所有 Android 版本,但它错过了向量的意义。
    • @androiddeveloper 最好不要使用未完成和有漏洞的 Android 操作系统。
    • layer-list 包装技巧门在远程视图(通知、应用程序)中不起作用,这是有道理的 :-)。
    【解决方案6】:

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

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

    【讨论】:

    • 等等,这意味着我们可以在项目中使用 SVG 文件了吗?无需在 IDE 中将它们转换为 VectorDrawable 吗?
    • 当然,我们需要。这里的 R.drawable.ic_map_black_24dp 是 SVG 源转换的结果。
    • 上面sn-p中的resources参数是什么?
    【解决方案7】:

    我遇到了一个问题,即我的矢量图像会显示但完全是黑色的,这是由于您无法在矢量 xml 文件中引用颜色资源的问题。

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

    【讨论】:

      【解决方案8】:

      VectorDrawable 通过支持库在棒棒糖之前得到支持,但使用它们的方式取决于您拥有的支持库的版本。而且它可能并非在所有情况下都有效。

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

      【讨论】:

      • 这是有史以来最好的答案。
      • 不幸的是,构建时 PNG 生成不支持对其他资源的引用,并且如果您在矢量可绘制对象中使用 android:fillColor="@color/dialog_button_text" 之类的东西会失败(因此排除支持库不仅会花费您知识库)。错误消息指向developer.android.com/tools/help/vector-asset-studio.html 了解详细信息。
      【解决方案9】:

      如果你使用的是 Android Studio 3.0.0 你可以设置

      android.enableAapt2=false 
      

      在 gradle.properties 中

      https://www.reddit.com/r/androiddev/comments/6mj8di/android_studio_30_canary_6_released/

      【讨论】:

        【解决方案10】:

        您可以以编程方式使用..将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
        【解决方案11】:

        为了兼容低版本,

        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);这有必要吗?
        • EditText 我想在哪里使用 drawableStart 呢?
        【解决方案12】:

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

        为避免 android:drawableleft in Textview 崩溃,请以编程方式将 drawble left 设置为 textview 例如:

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

        【讨论】:

          【解决方案13】:

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

          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);
          }
          
          • 我希望,它会对某人有所帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-14
            • 2018-12-09
            • 2016-11-11
            • 2019-06-05
            • 1970-01-01
            • 2017-12-07
            相关资源
            最近更新 更多