本周 Android Support 库发布了 23.2新版本,该版本包含了几个新功能。
支持 Vector Drawables 和 Animated Vector Drawables
使用矢量图的好处之一就是不用出多个图片(hdpi, xhdpi 等)了, 只需要一个矢量图即可涵盖所有屏幕密度的需要。矢量图在 Android 5.0 才开始支持,使用 23.2 support 库中的 support-vector-drawable 和 animated-vector-drawable 可以在之前的版本支持矢量图了。之前Android studio 在 build 的时候, 通过生成 PNG 图片来支持矢量图,要使用 23.2 版本中的矢量图功能,需要禁用之前版本的功能。如果你使用的 gradle 插件为 2.0+ 版本,则通过如下方式来启用新功能:
Java
// Gradle Plugin 2.0+
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
1
2
3
4
5
6
// Gradle Plugin 2.0+
android{
defaultConfig{
vectorDrawables.useSupportLibrary=true
}
}
如果你使用 1.5 的 gradle 插件,则需要通过如下的方式:
Java
// Gradle Plugin 1.5
android {
defaultConfig {
generatedDensities = []
}
// This is handled for you by the 2.0+ Gradle Plugin
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
1
2
3
4
5
6
7
8
9
10
11
// Gradle Plugin 1.5
android{
defaultConfig{
generatedDensities=[]
}
// This is handled for you by the 2.0+ Gradle Plugin
aaptOptions{
additionalParameters"--no-version-vectors"
}
}
然后就可以使用 VectorDrawableCompat 和 AnimatedVectorDrawableCompat 了,VectorDrawableCompat 最低可以在 API 7 版本上使用, 而 AnimatedVectorDrawableCompat 需要 API 11 版本。目前通过 AppCompat 库只支持 ImageView 和其子类(例如 ImageButton 和 FloatingActionButton)可以在布局文件中直接使用 矢量图,支持方式为使用 app:srcCompat 来替代 android:src,
XHTML
< ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_add" />
1
2
3
4
< ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_add"/>
如果在代码中设置矢量图,则和之前一样,可以直接使用 setImageResource() 。使用 AppCompat 和 app:srcCompat 是使用矢量图最简单的方式。
在5.0之前的版本除了 app:srcCompat 属性之外,其他属性都不支持矢量图,例如 TextView 的 android:drawableLeft ,你如果在该属性上使用矢量图,则在5.0之前的版本上会crash。但是,你如果把矢量图放到其他 Drawable 容器中,再使用这个 Drawable 容器可以支持5.0之前的版本,支持的容器有 StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable, 和 RotateDrawable。
你可以在 Drawable 容器中应用你的矢量图,例如通过 StateListDrawable 来引用矢量图,然后在 TextView 的 android:drawableLeft 中使用这个 StateListDrawable,这样在 5.0 之前的版本也可以使用矢量图了。
这样每个矢量图都需要放到一个 Drawable 容器中,可能比较繁琐,如果你使用 Data Binding 框架,则还可以又一个相对方便的方式。
定义一个 BindingAdapter, 该 BindingAdapter 把一个Drawable id 绑定到 TextView 的 drawableTop,
Java
public class Bindings {
@BindingAdapter({"bind:topId"})
public static void loadImage(TextView view, int topResId) {
view.setCompoundDrawablesWithIntrinsicBounds(0,topResId, 0,0);
}
}
1
2
3
4
5
6
7
8
publicclassBindings{
@BindingAdapter({"bind:topId"})
publicstaticvoidloadImage(TextViewview,inttopResId){
view.setCompoundDrawablesWithIntrinsicBounds(0,topResId,0,0);
}
}
然后在 布局文件中,使用这个自定义的 BindingAdapter,
XHTML
< ?xml version="1.0" encoding="utf-8"?>
< layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
< data>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
bind:topId="@{R.drawable.ic_favorite_outline_24dp}"
android:text="Hello World!" />
1
2
3
4
5
6
7
8
9
10
11
12
< ?xmlversion="1.0"encoding="utf-8"?>
< layoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
< data>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
bind:topId="@{R.drawable.ic_favorite_outline_24dp}"
android:text="Hello World!"/>
AppCompat DayNight 主题
除了支持矢量图以外,23.2版本中还保护了一个新的 Theme.AppCompat.DayNight主题。
在 API 14之前的版本,DayNight 主题和其子主题 ( DayNight.NoActionBar, DayNight.DarkActionBar, DayNight.Dialog 等) 都使用 白色主题替代。在 14+版本,则 DayNight 可以使应用很容易的同时支持白色和黑色主题,并且可以根据用户当前的时间自动切换主题,白天使用白色主题,夜晚使用黑色主题,是不是很酷。
默认情况下系统使用 UiModeManager.getNightMode() 来判断是否使用黑色主题。在 AppCompatDelegate 中可以重写该方法。通过函数 AppCompatDelegate.setDefaultNightMode() 可以设置整个应用的模式,也可以通过 getDelegate().setLocalNightMode() 函数来修改当前 Activity 和 Dialog 的主题。
如果使用 AppCompatDelegate.MODE_NIGHT_AUTO 模式,系统会根据当前的时间和设备最后已知的位置(需要您的应用具有位置权限)来自动切换主题。
如果你使用了 DayNight ,请全面测试你的应用在每个主题都可以使用,特别是文本和图标的颜色,如果你使用标准的 TextAppearance.AppCompat 来设置文字样式,或者从 android:textColorPrimary 来获取颜色,则系统会自动切换到合适的颜色。
除了这两个比较大的新功能以外,23.2 版本中还有如下改动,详细情况请参考这里:
Design 库中新加一个 bottom sheet 控件。
Support v4 的 MediaBrowserServiceCompat
RecyclerView 的自动计算本身大小的功能,这样 RecyclerView 就可以根据其内容的大小来设置自己的尺寸了。
Leanback for Android TV 中新的 GuidedStepFragment,更加方便的创建新手指引。