在 Lollipop 崩溃前使用 android vector Drawables [英] Using android vector Drawables on pre Lollipop crash

查看:22
本文介绍了在 Lollipop 崩溃前使用 android vector Drawables的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Lollipop 之前在 android 中使用矢量绘图,这些是我的一些库和工具版本:

  • Android 工作室:2.0
  • Android Gradle 插件:2.0.0
  • 构建工具:23.0.2
  • Android 支持库:23.3.0

我在我的应用程序级别添加了这个属性 Build.Gradle

android {默认配置{vectorDrawables.useSupportLibrary = true}}

还值得一提的是,我使用了一个额外的可绘制对象,例如 Android 官方博客中所述的 LayerDrawable(layer_list) (此处链接) 用于为 app:srcCompat

之外的矢量可绘制对象设置可绘制对象

<item android:drawable="@drawable/search"/></level-list>

<块引用>

你会发现直接引用了向量之外的可绘制对象app:srcCompat 将在 Lollipop 之前失败.但是,AppCompat 确实支持在另一个引用时加载矢量可绘制对象可绘制容器,例如 StateListDrawable、InsetDrawable、LayerDrawable、LevelListDrawable 和 RotateDrawable.通过使用这个indirection,可以在TextView等情况下使用vector drawablesandroid:drawableLeft 属性,通常无法支持向量可绘制.

当我使用 app:srcCompat 时一切正常,但是当我使用时:

android:background机器人:drawableLeftandroid:drawableRightandroid:drawableTop机器人:drawableBottom

ImageViewImageButtonTextViewEditText 在 Lollipop 之前,它抛出一个期望:

Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9

解决方案

最新更新 - 2019 年 6 月

自原始答案以来,支持库发生了一些变化.现在,即使是 Gradle 的 Android 插件也能够在构建时自动生成 PNG.因此,以下是目前应该有效的两种新方法.您可以在此处找到更多信息:

PNG 生成

Gradle 可以在构建时自动从您的资产创建 PNG 图像.但是,在这种方法中,并非所有 xml 元素都受支持.此解决方案很方便,因为您无需更改代码或 build.gradle 中的任何内容.只需确保您使用的是 Android 插件 1.5.0 或更高版本Android Studio 2.2 或更高版本.

我在我的应用中使用了这个解决方案并且工作正常.不需要额外的 build.gradle 标志.不需要黑客.如果您转到 /build/generated/res/pngs/...,您可以看到所有生成的 PNG.

因此,如果您有一些简单的图标(因为并非所有 xml 元素都受支持),此解决方案可能适合您.只需更新您的 Android Studio 和适用于 Gradle 的 Android 插件.

支持库

也许,这就是适合您的解决方案.如果您来到这里,则意味着您的 Android Studio 不会自动生成 PNG.所以,你的应用程序崩溃了.

或者,您可能根本不希望 Android Studio 生成任何 PNG.

与支持 XML 元素子集的自动 PNG 生成"不同,此解决方案支持所有 xml 标签.因此,您完全支持您的矢量可绘制对象.

您必须首先更新您的 build.gradle 以支持它:

android {默认配置{//此标志还将阻止 Android Studio 自动生成 PNGvectorDrawables.useSupportLibrary = true}}依赖{//将此用于支持库实现 'com.android.support:appcompat-v7:23.2.0'//或更高//将此用于 AndroidXimplementation 'androidx.appcompat:appcompat:1.1.0'//或更高}

然后,在加载 VectorDrawables 时使用 app:srcCompat 而不是 android:src.不要忘记这一点.

对于TextView,如果您使用的是androidx 版本的支持库,您可以使用app:drawableLeftCompat(或右侧,顶部, 底部) 而不是 app:drawableLeft

如果是 CheckBox/RadioButton,请使用 app:buttonCompat 而不是 android:button.>

如果您没有使用支持库的 androidx 版本,并且您的 minSdkVersion17 或更高或使用按钮,您可以尝试通过

以编程方式设置

Drawable icon = AppCompatResources.getDrawable(context, );textView.setCompoundDrawablesWithIntrinsicBounds(,,,);

<小时>

更新 - 2016 年 7 月

他们在
中重新启用了 VectorDrawableAndroid 支持库 23.4.0

<块引用>

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

也许build.gradle 设置现在已过时,您只需要在适当的活动中启用它(但是,需要测试).

现在,要启用它,您必须执行以下操作:

公共类 MainActivity 扩展 AppCompatActivity {静止的 {AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);}...}

<小时>

原始答案 - 2016 年 4 月

我认为这是因为在最新的库版本中禁用了支持向量:23.3.0

根据此POST:

<块引用>

对于 AppCompat 用户,由于在 23.2.0/23.2.1 版本的实施中发现了问题,我们决定删除允许您从棒棒糖之前设备上的资源中使用矢量可绘制对象的功能(问题 205236).使用 app:srcCompat 和 setImageResource() 继续工作.

如果您访问 issue ISSUE 205236,似乎它们将在未来启用,但内存问题不会很快得到修复:

<块引用>

在下一个版本中,我添加了一个选择加入的 API,您可以在其中重新启用已删除的 VectorDrawable 支持.但它带有与以前相同的警告(内存使用和配置更新问题).

我遇到了类似的问题.因此,就我而言,我再次将所有使用矢量可绘制的图标从资源恢复为 PNG 图像(因为即使在提供再次启用它的选项后,内存问题仍会继续发生).

我不确定这是否是最佳选择,但在我看来它修复了所有崩溃问题.

I'm using vector drawables in android prior to Lollipop and these are of some of my libraries and tool versions:

  • Android Studio : 2.0
  • Android Gradle Plugin : 2.0.0
  • Build Tools : 23.0.2
  • Android Support Library : 23.3.0

I added this property in my app level Build.Gradle

android {  
  defaultConfig {  
    vectorDrawables.useSupportLibrary = true  
   }  
}

It is also worth mentioning that I use an extra drawable such as LayerDrawable(layer_list) as stated in Android official Blog (link here) for setting drawables for vector drawables outside of app:srcCompat

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

You’ll find directly referencing vector drawables outside of app:srcCompat will fail prior to Lollipop. However, AppCompat does support loading vector drawables when they are referenced in another drawable container such as a StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable, and RotateDrawable. By using this indirection, you can use vector drawables in cases such as TextView’s android:drawableLeft attribute, which wouldn’t normally be able to support vector drawables.

When I'm using app:srcCompat everything works fine, but when I use:

android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom

on ImageView, ImageButton, TextView or EditText prior to Lollipop, it throws an expection:

Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9

解决方案

LATEST UPDATE - Jun/2019

Support Library has changed a bit since the original answer. Now, even the Android plugin for Gradle is able to automatically generate the PNG at build time. So, below are two new approaches that should work these days. You can find more info here:

PNG Generation

Gradle can automatically create PNG images from your assets at build time. However, in this approach, not all xml elements are supported. This solution is convenient because you don't need to change anything in your code or in your build.gradle. Just make sure you are using Android Plugin 1.5.0 or higher and Android Studio 2.2 or higher.

I'm using this solution in my app and works fine. No additional build.gradle flag necessary. No hacks is necessary. If you go to /build/generated/res/pngs/... you can see all generated PNGs.

So, if you have some simple icon (since not all xml elements are supported), this solution may work for you. Just update your Android Studio and your Android plugin for Gradle.

Support Library

Probably, this is the solution that will work for you. If you came here, it means your Android Studio is not generating the PNGs automatically. So, your app is crashing.

Or maybe, you don't want Android Studio to generate any PNG at all.

Differently from that "Auto-PNG generation" which supports a subset of XML element, this solution, supports all xml tags. So, you have full support to your vector drawable.

You must first, update your build.gradle to support it:

android {
  defaultConfig {
    // This flag will also prevents Android Studio from generating PNGs automatically
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  // Use this for Support Library
  implementation 'com.android.support:appcompat-v7:23.2.0' // OR HIGHER

  // Use this for AndroidX
  implementation 'androidx.appcompat:appcompat:1.1.0' // OR HIGHER
}

And then, use app:srcCompat instead of android:src while loading VectorDrawables. Don't forget this.

For TextView, if you are using the androidx version of the Support Library, you can use app:drawableLeftCompat (or right, top, bottom) instead of app:drawableLeft

In case of CheckBox/RadioButton, use app:buttonCompat instead of android:button.

If you are not using the androidx version of the Support Library and your minSdkVersion is 17 or higher or using a button, you may try to set programmatically via

Drawable icon = AppCompatResources.getDrawable(context, <drawable_id>);
textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);


UPDATE - Jul/2016

They re-enabled that VectorDrawable in
Android Support Library 23.4.0

For AppCompat users, we’ve added an opt-in API to re-enable support Vector Drawables from resources (the behavior found in 23.2) via AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) - keep in mind that this still can cause issues with memory usage and problems updating Configuration instances, hence why it is disabled by default.

Maybe, build.gradle setting is now obsolete and you just need to enable it in proper activities (however, need to test).

Now, to enable it, you must do:

public class MainActivity extends AppCompatActivity {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    ...
}


Original Answer - Apr/2016

I think this is happening because Support Vector was disabled in the latest library version: 23.3.0

According to this POST:

For AppCompat users, we’ve decided to remove the functionality which let you use vector drawables from resources on pre-Lollipop devices due to issues found in the implementation in version 23.2.0/23.2.1 (ISSUE 205236). Using app:srcCompat and setImageResource() continues to work.

If you visit issue ISSUE 205236, it seems that they will enable in the future but the memory issue will not be fixed soon:

In the next release I've added an opt-in API where you can re-enable the VectorDrawable support which was removed. It comes with the same caveats as before though (memory usage and problems with Configuration updating).

I had a similar issue. So, in my case, I reverted all icons which use vector drawable from resource to PNG images again (since the memory issue will keep happening even after they provide an option to enable it again).

I'm not sure if this is the best option, but it fixes all the crashes in my opinion.

这篇关于在 Lollipop 崩溃前使用 android vector Drawables的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆