我遇到了与VectorDrawables新的向后兼容性问题。 在支持库中,23.2是一个新功能,用于向后兼容所生成的Android VectorDrawables。
我有一个ImageView,它是一个分配给的SelectorDrawable。这个Drawable拥有几个VectorDrawables所以我认为我应该使用app:srcCompat来兼容。但它在我的Galaxy S2上不适用于android 4.1.2。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_gps_fixed_24dp"android:state_activated="true" android:state_selected="true"></item>
<item android:drawable="@drawable/ic_gps_not_fixed_24dp" android:state_activated="true" android:state_selected="false"></item>
<item android:drawable="@drawable/ic_gps_not_fixed_24dp" android:state_activated="false" android:state_selected="true"></item>
<item android:drawable="@drawable/ic_gps_off_24dp" android:state_activated="false" android:state_selected="false"></item>
<item android:drawable="@drawable/ic_gps_not_fixed_24dp"></item>
</selector>
所有drawables都是vector xml文件。
将此SelectorDrawable与srcCompat一起使用时,出现此错误:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_gps_fixed_24dp.xml from drawable resource ID #0x7f0201c1
at android.content.res.Resources.loadDrawable(Resources.java:1951)
at android.content.res.Resources.getDrawable(Resources.java:672)
at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173)
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:881).xml from drawable resource ID #0x7f0201c1
使用android:src更糟糕。
如果我使用app:srcCompat中的一个矢量drawable,一切正常。所以我猜这是SelectorDrawable和兼容性的问题。
有没有人遇到同样的问题并找到解决方案,或者目前无法在Android 5之前的SelectorDrawables中使用VectorDrawables?
简要说明:
答案 0 :(得分:63)
借助支持库23.4.0,重新启用了对来自Ressources的VectorDrawables的支持:Android Support Library 23.4.0 available now
您可以在Google I / O 2016的演员阵容中找到更多相关信息: What's new in the support library - Google I/O 2016
你需要将这个添加到你想在Android 5.0以下的设备上使用VectorDrawables的每个Activity(Codename Lollipop,API level 21):
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
所以你现在可以在DrawableContainers中使用VectorDrawables,但它仍然会引起上面提到的一些问题,所以请谨慎使用。
到目前为止,我的应用程序中没有重新启用此功能,但我会在下一个主要版本中将很多图标更改为VectorDrawables,然后将深入探讨此主题。
答案 1 :(得分:53)
正如@Jahnold在评论中提到的那样,在23.3中删除了从xml状态xml列表中加载vector drawable的支持。
但是,我找到了几种可以提供帮助的方法。
<强> 1。使用色调
如果来自所选状态列表的可绘制列表仅通过颜色区别,则该方法是合适的。
首先,只创建一个带有色调和白色fillColor
的可绘制矢量:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tintMode="multiply"
android:tint="@color/button_tint">
<path
android:fillColor="#ffffff"
android:pathData="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
<path
android:pathData="M0 0h24v24H0z"/>
</vector>
其次,创建放置在button_tint.xml
res/color
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#555555" android:state_enabled="false"/>
<item android:color="#6699dd"/>
</selector>
不要忘记向build.gradle
添加以下行,否则该方法将不适用于旧的Android版本。
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
<强> 2。硬编码创建StateListDrawable
如果您使用状态列表矢量drawables,这种方法是合适的,这不仅可以区分颜色,还可以通过图形区别,因此您需要创建多个不同的xml文件。然后,您可以按answer。
中所示的方式以编程方式创建StateListDrawable
答案 2 :(得分:7)
观看支持库中的新功能 - Google I / O 2016 后,我注意到AppCompatResources
课程中有一种有用的方法。这是AppCompatResources#getColorStateList(Context context, int resId)
。在这种方法的帮助下,我实现了带有矢量绘图的选择器。这是我的颜色选择器文件icon_selector
:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/red_selected" android:state_selected="true"/>
<item android:color="@color/red_pressed" android:state_pressed="true"/>
<item android:color="@color/red"/>
</selector>
还有java方法返回tinted drawable:
private Drawable getTintedDrawable(@DrawableRes int drawableId) {
Drawable drawable;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
drawable = getResources().getDrawable(drawableId, getTheme());
} else {
drawable = getResources().getDrawable(drawableId);
}
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTintList(drawable.mutate(), AppCompatResources.getColorStateList(this, R.color.selector_nav_bar_item_ico));
return drawable;
}
您可以使用它,如下所示
yourImageView.setImageDrawable(getTintedDrawable(R.drawable.ic_vector_image));
答案 3 :(得分:2)
以下更改正常工作。
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
在应用程序类中添加 default buildConfig中的app build.gradle
vectorDrawables.useSupportLibrary = true
答案 4 :(得分:1)
我建议采用以下变通方法来根据状态进行颜色更改: 设置一个普通的白色VectorDrawable,并使颜色具有颜色选择器。
经过测试,即使在使用Android API 16的模拟器上也可以使用,并且即使在gradle中设置了“ vectorDrawables.useSupportLibrary = true”,它也可以正常工作。
示例:启用第一个视图,然后禁用第二个视图:
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
disabledSendMessageButton.isEnabled = false
}
}
res / layout / activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false"
android:clipToPadding="false" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/sendMessageButton" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:focusable="true" android:foreground="?attr/selectableItemBackgroundBorderless"
android:minWidth="?attr/actionBarSize" android:minHeight="?attr/actionBarSize" android:padding="8dp"
android:scaleType="centerInside" app:srcCompat="@drawable/ic_baseline_send_24" app:tint="@color/color_selector"
tools:targetApi="m" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/disabledSendMessageButton" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:clickable="true" android:focusable="true"
android:foreground="?attr/selectableItemBackgroundBorderless" android:minWidth="?attr/actionBarSize"
android:minHeight="?attr/actionBarSize" android:padding="8dp" android:scaleType="centerInside"
app:srcCompat="@drawable/ic_baseline_send_24" app:tint="@color/color_selector" tools:targetApi="m" />
</LinearLayout>
res / color / color_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/secondary_text_dark" android:state_enabled="false" />
<item android:color="@color/colorPrimary" />
</selector>
res / drawable / ic_baseline_send_24.xml
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>
答案 5 :(得分:0)
使用animated-selector
示例
https://github.com/alexjlockwood/adp-delightful-details
https://www.androiddesignpatterns.com/2016/11/introduction-to-icon-animation-techniques.html
使用此工具创建 animated-vector
文件