Android之VectorDrawable

之前官方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

猜你喜欢

转载自blog.csdn.net/Lboshao/article/details/50879024