之前官方VectorDrawable只支持api 21以上,前不久android support libriry 23.2.0出来了,VectorDrawable终于可以向下兼容了。相比之前图片来说,矢量图可以解决不同尺寸手机图片失真问题,可以不用多套图片去适配不同尺寸手机,还可以减少apk体积.官方的icon全都提供svg的版本:material design icon
注意:矢量图形的初始加载可能花费比一般图像占用更多的CPU。之后内存使用和性能两者之间相似。官方建议矢量图像不要超过200×200dp.
使用很简单,下面提供几种svg转xml的方法:
- android studio 支持预览VectorDrawalbe[要求:Android Plugin for Gradle 1.5.0 or higher.]
- 在android studio选择project窗口, New > Vector Asset.
- svg转xml, 有很多工具:这是个开源的工具
- android studio svg转xml的插件: https://github.com/misakuo/svgtoandroid
直接在ImageView引用drawable即可:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_share_black_24px"
/>
iv.setImageResource(R.drawable.ic_share_black_24px);
代码中使用:
iv.setImageResource(R.drawable.ic_share_black_24px);
一直好奇官方怎么向下兼容一些控件的,今天跟踪了下源码看看怎么兼容VerctorDrawable:
定位到:AppCompatImageView.java
public AppCompatImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(TintContextWrapper.wrap(context), attrs, defStyleAttr);
final AppCompatDrawableManager drawableManager = AppCompatDrawableManager.get();
mBackgroundTintHelper = new AppCompatBackgroundHelper(this, drawableManager);
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
mImageHelper = new AppCompatImageHelper(this, drawableManager);
mImageHelper.loadFromAttributes(attrs, defStyleAttr);
}
@Override
public void setImageResource(@DrawableRes int resId) {
// Intercept this call and instead retrieve the Drawable via the image helper
mImageHelper.setImageResource(resId);
}
再看AppCompatImageHelper.java 的loadFromAttributes()
public void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
R.styleable.AppCompatImageView, defStyleAttr, 0);
try {
Drawable d = a.getDrawableIfKnown(R.styleable.AppCompatImageView_android_src);
if (d != null) {
mView.setImageDrawable(d);
}
//AppCompatImageView 继承ImageView, 比ImageView多 app:srcCompat属性
final int id = a.getResourceId(R.styleable.AppCompatImageView_srcCompat, -1);
if (id != -1) {
d = mDrawableManager.getDrawable(mView.getContext(), id);
if (d != null) {
mView.setImageDrawable(d);
}
}
final Drawable drawable = mView.getDrawable();
if (drawable != null) {
DrawableUtils.fixDrawable(drawable);
}
} finally {
a.recycle();
}
}
AppCompatViewInflater.java 的 final View createView():
View view = null;
// We need to 'inject' our tint aware Views in place of the standard framework versions
switch (name) {
case "TextView":
view = new AppCompatTextView(context, attrs);
break;
case "ImageView":
view = new AppCompatImageView(context, attrs);
break;
case "Button":
view = new AppCompatButton(context, attrs);
break;
看到这里似乎懂了,低版本的布局文件里的ImageView会主动转成AppCompatImageView,
最后由AppCompatImageHelper处理兼容性问题.
更多内容参考:
- Vector Asset Studio
- VectorDrawable-part-1
- VectorDrawable-part-2
- VectorDrawable-part-3
- VectorDrawable-part-4