在 Lollipop 崩溃前使用 android 矢量可绘制对象
Using android vector Drawables on pre Lollipop crash
我在 android Lollipop 之前使用矢量绘图,这些是我的一些库和工具版本:
- Android 工作室:2.0
- Android Gradle 插件:2.0.0
- 构建工具:23.0.2
- Android 支持库:23.3.0
我在我的应用级别 Build.Gradle
添加了这个 属性
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
另外值得一提的是,我在Android官方博客(link here)中使用了一个额外的drawable,例如LayerDrawable(layer_list)来为外部的矢量drawables设置drawables共 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.
当我使用 app:srcCompat
时一切正常,但是当我使用:
android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom
在 Lollipop 之前的 ImageView
、ImageButton
、TextView
或 EditText
上,它抛出一个预期:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
最新更新 - Jun/2019
支持库自原始答案以来发生了一些变化。现在,甚至 Gradle 的 Android 插件也能够在构建时自动生成 PNG。因此,以下是目前应该有效的两种新方法。您可以找到更多信息 here:
PNG 生成
Gradle 可以在构建时从您的资产自动创建 PNG 图像。但是,在这种方法中,并非所有 xml 元素都受支持。此解决方案很方便,因为您不需要更改代码或 build.gradle 中的任何内容。只需确保您使用的是 Android 插件 1.5.0 或更高版本 和 Android Studio 2.2 或更高版本.
我在我的应用程序中使用这个解决方案并且工作正常。不需要额外的 build.gradle 标志。没有黑客是必要的。如果你去 /build/generated/res/pngs/... 你可以看到所有生成的 PNG。
因此,如果您有一些简单的图标(因为并非所有 xml 元素都受支持),此解决方案可能适合您。只需为 Gradle.
更新您的 Android Studio 和 Android 插件
支持库
这可能是适合您的解决方案。如果您来到这里,则意味着您的 Android Studio 没有自动生成 PNG。所以,你的应用程序崩溃了。
或者,您可能根本不希望 Android Studio 生成任何 PNG。
与支持 XML 元素子集的 "Auto-PNG generation" 不同,此解决方案支持所有 xml 标签。因此,您完全支持您的矢量绘图。
您必须先更新您的 build.gradle 以支持它:
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
}
然后,在加载 VectorDrawables
时使用 app:srcCompat
而不是 android:src
。不要忘记这一点。
对于TextView
,如果你使用的是androidx
版本的Support Library,你可以使用app:drawableLeftCompat
(或者right, top, bottom)代替app:drawableLeft
在 CheckBox
/RadioButton
的情况下,使用 app:buttonCompat
而不是 android:button
。
如果您没有使用 androidx
版本的支持库并且您的 minSdkVersion
是 17
或更高版本或使用按钮,您可以尝试通过
Drawable icon = AppCompatResources.getDrawable(context, <drawable_id>);
textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);
更新 - Jul/2016
他们在
中重新启用了 VectorDrawable
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.
也许,build.gradle
设置现在已经过时,您只需要在适当的活动中启用它(但是,需要测试)。
现在,要启用它,您必须执行以下操作:
public class MainActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
...
}
原始答案 - Apr/2016
我认为这是因为支持向量在最新的库版本中被禁用:23.3.0
根据这个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.
如果你访问问题 ISSUE 205236,他们似乎会在未来启用,但内存问题不会很快修复:
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).
我遇到了类似的问题。因此,就我而言,我再次将所有使用可绘制矢量的图标从资源还原为 PNG 图像(因为即使在它们提供了再次启用它的选项后内存问题仍会继续发生)。
我不确定这是否是最佳选择,但我认为它修复了所有崩溃问题。
Guillherme P 的回答非常棒。只是为了做一个小改进,您不需要在每个 activity 中都添加该行,如果您在应用程序 class 中添加一次它也可以正常工作。
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
记住:您仍然需要在 gradle 中启用支持库的使用:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
此外,请确保您使用的支持库版本大于 v23.4,当 Google 为 VectorDrawables (release note)
添加了对 Drawable Container 的支持时
更新
对于代码更改:
- 确保更新到
app:srcCompat
每个接受 android:src
属性的地方(IDE 会在无效时警告您,就像 <bitmap>
标签一样)。
对于 drawableLeft
、drawableStart
、drawableRight
、drawableEnd
TextView
和类似视图中使用的属性,您必须现在以编程方式设置它们。设置示例 drawableStart
:
Drawable drawable = AppCompatResources.getDrawable(
getContext(),
R.drawable.your_vector_drawable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null);
}
替代 Benny 的 答案是创建一个 Activity
超类:
public abstract class VectorDrawableActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
//...
}
现在扩展 VectorDrawableActivity
而不是 AppCompatActivity
。
pre-lollipop 上的 VectorDrawables 在不使用
的情况下应该可以正常工作
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
如果你想在 ImageViews 中使用 VectorDrawables,你可以使用属性 srcCompat
并且它会起作用,但在 Buttons 或 TextViews 中它不会,所以您需要将 Drawable 包装到 InsetDrawable 或 LayerDrawable 中。我发现了另一个技巧,如果你使用数据绑定,你可以这样做:
android:drawableLeft="@{@drawable/vector_ic_access_time_24px}"
android:drawableStart="@{@drawable/vector_ic_access_time_24px}"
这会神奇地起作用,我没有调查幕后发生的事情,但我猜 TextView 正在使用 AppCompatResources 或类似方法中的 getDrawable 方法。
详细说明其他, here is a diagram可以帮助你的。如果你有从 23.4.0 到至少 25.1.0 的支持库,它是有效的。
Guilherme P 的建议对我不起作用。我继续并决定在我需要在 app:srcCompat 之外做事的地方使用 png,即 drawableLeft、drawableRight 等。这是一个很容易做出的改变,并且没有潜在的内存问题 AppCompatDelegate.setCompatVectorFromResourcesEnabled(真);
介绍。
我遇到了同样的问题。
但是做了很多研发我得到了答案。
对于Imageview和ImageButton的使用,app:srcCompat="@drawable/...."
对于 Button、Textview 等其他视图,不要在 XML 中使用 "drawableLeft/right..."
,而是以编程方式将可绘制对象指定为:
button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);
并使用 "AppCompatResources" 获取可绘制对象。
我遇到了同样的问题。并通过删除
来修复它
vectorDrawables.useSupportLibrary = true
我的目标版本是 25,支持库是
compile 'com.android.support:appcompat-v7:25.3.1'
我在 Pre-lollipop 设备上使用 VectorDrawables,我就是这样做的 :-
第 1 步:
将其放入您的应用级别 gradle。
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
第 2 步:
将其放入您的应用程序 class 并且不要忘记在清单文件中注册您的应用程序 class。
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
}
第 3 步:
使用
获取VectorDrawables
imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
升级到android gradle 3.0及以上版本的,不需要使用AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
,或者设置vectorDrawables.useSupportLibrary = true
(加这个会出问题)并使用 app:srcCompat
,效果很好。
我花了两天时间弄明白了,在google的文档中没有找到任何相关文档...
大量的研发,终于得到了这个解决前棒棒糖设备崩溃的方法。
对于图像视图
- use app:srcCompat instead of android:src
对于TextView/EditText
- Remove drawableleft,drawableright.... and set from drawable java code.
txtview.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(EventDetailSinglePage.this,
R.drawable.ic_done_black_24_n), null, null, null);
对于Build.gradle
vectorDrawables.useSupportLibrary = true
只需将矢量绘图重叠到状态列表即可解决问题
例如你有后退箭头矢量图:
ic_back_arrow.xml
是的,你应该将它重叠到图层列表 xml (ic_back_arrow_vector_vector.xml):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_back_arrow"/>
</layer-list>
因为逻辑:
vectorDrawables.useSupportLibrary = true
和
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
不会在某些中国设备和较旧的三星设备上帮助您。如果你不重叠它们,它将失败。
最简单的使用方法:
app:drawableRightCompat ="@drawable/ic_mobilelogin"
app:drawableEndCompat="@drawable/ic_mobilelogin"
app:srcCompat="@drawable/ic_mobile"
并且...只需使用 app:**Compat
即可实现兼容性。
同时添加对 build.gradle
(模块)
的支持
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
使用下面的代码后。
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}}
仍然存在以下属性的矢量图像问题
可绘制结束,
绘图开始,
可绘制顶部,
可绘制底部,
背景
在这种情况下,请按照以下步骤操作,而不是直接引用矢量图像,而是使用选择器标记作为中间可绘制文件。
示例:
ic_warranty_icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="17"
android:viewportHeight="24">
<path
android:fillColor="#fff"
android:pathData="M10.927,15.589l-1.549,0.355a7.47,7.47 0,0 1,-0.878 0.056c-4.136,0 -7.5,-3.364 -7.5,-7.5s3.364,-7.5 7.5,-7.5 7.5,3.364 7.5,7.5c0,3.286 -2.126,6.078 -5.073,7.089zM8.5,2a6.508,6.508 0,0 0,-6.5 6.5c0,3.583 2.917,6.5 6.5,6.5s6.5,-2.917 6.5,-6.5 -2.917,-6.5 -6.5,-6.5z" />
safe_ic_warranty_icon.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_warranty_icon" />
</selector>
你的TextView/Layout.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_warranty_icon"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_warranty_icon"
/>
我们尝试了 3 件事
vectorDrawables.useSupportLibrary = true
在应用程序中设置 setCompatVectorFromResourcesEnabled class
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
并使用 app:srcCompat
但即使在那之后它还是失败了
Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008
然后我们发现我们的 SVG 有一个渐变标签。
将渐变标记转换为 API <= 23 以下的单独路径并使用相同的 SVG API >= 24 有效。
从这个回答中得到了帮助
我为此苦苦挣扎了几个小时。
我尝试了这些答案告诉我的所有事情,但我的应用程序并没有停止崩溃。我删除了这一行:app:srcCompat="@drawable/keyboard"
并且我的应用停止了崩溃。然后当我把同样的东西加回去时,它又开始崩溃了。所以我决定打开那个文件,我在第一行看到一个错误
"The drawable 'Keyboard' has no declaration in the base drawable
folder; this can lead to crashes.
我右击了文件,点了"Show in explorer",发现它不在drawable文件夹里,而是在drawable-v24目录下。所以我把它复制并粘贴到drawable目录,终于摆脱了崩溃。
就我而言,我使用的是 TabLayout
,我将其配置为:
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_list, theme)
else
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_building_map, theme)
}.attach()
应用程序在第 tab.icon = ...
行崩溃
我将这些更改为 tab.setIcon(R.drawable.my_vector_asset)
,因为它:
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.setIcon(R.drawable.ic_list)
else
tab.setIcon(R.drawable.ic_building_map)
}.attach()
成功了!
我在 android Lollipop 之前使用矢量绘图,这些是我的一些库和工具版本:
- Android 工作室:2.0
- Android Gradle 插件:2.0.0
- 构建工具:23.0.2
- Android 支持库:23.3.0
我在我的应用级别 Build.Gradle
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
另外值得一提的是,我在Android官方博客(link here)中使用了一个额外的drawable,例如LayerDrawable(layer_list)来为外部的矢量drawables设置drawables共 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.
当我使用 app:srcCompat
时一切正常,但是当我使用:
android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom
在 Lollipop 之前的 ImageView
、ImageButton
、TextView
或 EditText
上,它抛出一个预期:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
最新更新 - Jun/2019
支持库自原始答案以来发生了一些变化。现在,甚至 Gradle 的 Android 插件也能够在构建时自动生成 PNG。因此,以下是目前应该有效的两种新方法。您可以找到更多信息 here:
PNG 生成
Gradle 可以在构建时从您的资产自动创建 PNG 图像。但是,在这种方法中,并非所有 xml 元素都受支持。此解决方案很方便,因为您不需要更改代码或 build.gradle 中的任何内容。只需确保您使用的是 Android 插件 1.5.0 或更高版本 和 Android Studio 2.2 或更高版本.
我在我的应用程序中使用这个解决方案并且工作正常。不需要额外的 build.gradle 标志。没有黑客是必要的。如果你去 /build/generated/res/pngs/... 你可以看到所有生成的 PNG。
因此,如果您有一些简单的图标(因为并非所有 xml 元素都受支持),此解决方案可能适合您。只需为 Gradle.
更新您的 Android Studio 和 Android 插件支持库
这可能是适合您的解决方案。如果您来到这里,则意味着您的 Android Studio 没有自动生成 PNG。所以,你的应用程序崩溃了。
或者,您可能根本不希望 Android Studio 生成任何 PNG。
与支持 XML 元素子集的 "Auto-PNG generation" 不同,此解决方案支持所有 xml 标签。因此,您完全支持您的矢量绘图。
您必须先更新您的 build.gradle 以支持它:
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
}
然后,在加载 VectorDrawables
时使用 app:srcCompat
而不是 android:src
。不要忘记这一点。
对于TextView
,如果你使用的是androidx
版本的Support Library,你可以使用app:drawableLeftCompat
(或者right, top, bottom)代替app:drawableLeft
在 CheckBox
/RadioButton
的情况下,使用 app:buttonCompat
而不是 android:button
。
如果您没有使用 androidx
版本的支持库并且您的 minSdkVersion
是 17
或更高版本或使用按钮,您可以尝试通过
Drawable icon = AppCompatResources.getDrawable(context, <drawable_id>);
textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);
更新 - Jul/2016
他们在
中重新启用了 VectorDrawable
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.
也许,build.gradle
设置现在已经过时,您只需要在适当的活动中启用它(但是,需要测试)。
现在,要启用它,您必须执行以下操作:
public class MainActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
...
}
原始答案 - Apr/2016
我认为这是因为支持向量在最新的库版本中被禁用:23.3.0
根据这个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.
如果你访问问题 ISSUE 205236,他们似乎会在未来启用,但内存问题不会很快修复:
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).
我遇到了类似的问题。因此,就我而言,我再次将所有使用可绘制矢量的图标从资源还原为 PNG 图像(因为即使在它们提供了再次启用它的选项后内存问题仍会继续发生)。
我不确定这是否是最佳选择,但我认为它修复了所有崩溃问题。
Guillherme P 的回答非常棒。只是为了做一个小改进,您不需要在每个 activity 中都添加该行,如果您在应用程序 class 中添加一次它也可以正常工作。
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
记住:您仍然需要在 gradle 中启用支持库的使用:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
此外,请确保您使用的支持库版本大于 v23.4,当 Google 为 VectorDrawables (release note)
添加了对 Drawable Container 的支持时更新
对于代码更改:
- 确保更新到
app:srcCompat
每个接受android:src
属性的地方(IDE 会在无效时警告您,就像<bitmap>
标签一样)。 对于
drawableLeft
、drawableStart
、drawableRight
、drawableEnd
TextView
和类似视图中使用的属性,您必须现在以编程方式设置它们。设置示例drawableStart
:Drawable drawable = AppCompatResources.getDrawable( getContext(), R.drawable.your_vector_drawable); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null); }
替代 Benny 的 答案是创建一个 Activity
超类:
public abstract class VectorDrawableActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
//...
}
现在扩展 VectorDrawableActivity
而不是 AppCompatActivity
。
pre-lollipop 上的 VectorDrawables 在不使用
的情况下应该可以正常工作AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
如果你想在 ImageViews 中使用 VectorDrawables,你可以使用属性 srcCompat
并且它会起作用,但在 Buttons 或 TextViews 中它不会,所以您需要将 Drawable 包装到 InsetDrawable 或 LayerDrawable 中。我发现了另一个技巧,如果你使用数据绑定,你可以这样做:
android:drawableLeft="@{@drawable/vector_ic_access_time_24px}"
android:drawableStart="@{@drawable/vector_ic_access_time_24px}"
这会神奇地起作用,我没有调查幕后发生的事情,但我猜 TextView 正在使用 AppCompatResources 或类似方法中的 getDrawable 方法。
详细说明其他
Guilherme P 的建议对我不起作用。我继续并决定在我需要在 app:srcCompat 之外做事的地方使用 png,即 drawableLeft、drawableRight 等。这是一个很容易做出的改变,并且没有潜在的内存问题 AppCompatDelegate.setCompatVectorFromResourcesEnabled(真); 介绍。
我遇到了同样的问题。 但是做了很多研发我得到了答案。
对于Imageview和ImageButton的使用,app:srcCompat="@drawable/...."
对于 Button、Textview 等其他视图,不要在 XML 中使用 "drawableLeft/right..."
,而是以编程方式将可绘制对象指定为:
button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);
并使用 "AppCompatResources" 获取可绘制对象。
我遇到了同样的问题。并通过删除
来修复它vectorDrawables.useSupportLibrary = true
我的目标版本是 25,支持库是
compile 'com.android.support:appcompat-v7:25.3.1'
我在 Pre-lollipop 设备上使用 VectorDrawables,我就是这样做的 :-
第 1 步: 将其放入您的应用级别 gradle。
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
第 2 步:
将其放入您的应用程序 class 并且不要忘记在清单文件中注册您的应用程序 class。
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
}
第 3 步:
使用
获取VectorDrawablesimageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
升级到android gradle 3.0及以上版本的,不需要使用AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
,或者设置vectorDrawables.useSupportLibrary = true
(加这个会出问题)并使用 app:srcCompat
,效果很好。
我花了两天时间弄明白了,在google的文档中没有找到任何相关文档...
大量的研发,终于得到了这个解决前棒棒糖设备崩溃的方法。
对于图像视图
- use app:srcCompat instead of android:src
对于TextView/EditText
- Remove drawableleft,drawableright.... and set from drawable java code.
txtview.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(EventDetailSinglePage.this, R.drawable.ic_done_black_24_n), null, null, null);
对于Build.gradle
vectorDrawables.useSupportLibrary = true
只需将矢量绘图重叠到状态列表即可解决问题
例如你有后退箭头矢量图:
ic_back_arrow.xml
是的,你应该将它重叠到图层列表 xml (ic_back_arrow_vector_vector.xml):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_back_arrow"/>
</layer-list>
因为逻辑:
vectorDrawables.useSupportLibrary = true
和
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
不会在某些中国设备和较旧的三星设备上帮助您。如果你不重叠它们,它将失败。
最简单的使用方法:
app:drawableRightCompat ="@drawable/ic_mobilelogin"
app:drawableEndCompat="@drawable/ic_mobilelogin"
app:srcCompat="@drawable/ic_mobile"
并且...只需使用 app:**Compat
即可实现兼容性。
同时添加对 build.gradle
(模块)
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
使用下面的代码后。
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}}
仍然存在以下属性的矢量图像问题
可绘制结束, 绘图开始, 可绘制顶部, 可绘制底部, 背景
在这种情况下,请按照以下步骤操作,而不是直接引用矢量图像,而是使用选择器标记作为中间可绘制文件。
示例:
ic_warranty_icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="17"
android:viewportHeight="24">
<path
android:fillColor="#fff"
android:pathData="M10.927,15.589l-1.549,0.355a7.47,7.47 0,0 1,-0.878 0.056c-4.136,0 -7.5,-3.364 -7.5,-7.5s3.364,-7.5 7.5,-7.5 7.5,3.364 7.5,7.5c0,3.286 -2.126,6.078 -5.073,7.089zM8.5,2a6.508,6.508 0,0 0,-6.5 6.5c0,3.583 2.917,6.5 6.5,6.5s6.5,-2.917 6.5,-6.5 -2.917,-6.5 -6.5,-6.5z" />
safe_ic_warranty_icon.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_warranty_icon" />
</selector>
你的TextView/Layout.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_warranty_icon"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_warranty_icon"
/>
我们尝试了 3 件事
vectorDrawables.useSupportLibrary = true
在应用程序中设置 setCompatVectorFromResourcesEnabled class
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
并使用 app:srcCompat
但即使在那之后它还是失败了
Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008
然后我们发现我们的 SVG 有一个渐变标签。 将渐变标记转换为 API <= 23 以下的单独路径并使用相同的 SVG API >= 24 有效。
从这个回答中得到了帮助
我为此苦苦挣扎了几个小时。
我尝试了这些答案告诉我的所有事情,但我的应用程序并没有停止崩溃。我删除了这一行:app:srcCompat="@drawable/keyboard"
并且我的应用停止了崩溃。然后当我把同样的东西加回去时,它又开始崩溃了。所以我决定打开那个文件,我在第一行看到一个错误
"The drawable 'Keyboard' has no declaration in the base drawable folder; this can lead to crashes.
我右击了文件,点了"Show in explorer",发现它不在drawable文件夹里,而是在drawable-v24目录下。所以我把它复制并粘贴到drawable目录,终于摆脱了崩溃。
就我而言,我使用的是 TabLayout
,我将其配置为:
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_list, theme)
else
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_building_map, theme)
}.attach()
应用程序在第 tab.icon = ...
我将这些更改为 tab.setIcon(R.drawable.my_vector_asset)
,因为它:
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.setIcon(R.drawable.ic_list)
else
tab.setIcon(R.drawable.ic_building_map)
}.attach()
成功了!