Android优化UI(一)

Drawable文件

Drawable文件夹主要用于存放应用程序中的可绘制图形对象资源,这些可绘制对象资源可以是:位图文件(BitmapDrawable),九宫格文件( NinePatchDrawable),图层列表(LayerDrawable),状态列表(StateListDrawable),级别列表(LevelListDrawable),转换可绘制对象(TransitionDrawable),插入可绘制对象,裁剪可绘制对象( ClipDrawable),缩放可绘制对象(ScaleDrawable),形状可绘制对象(ShapeDrawable)。

其中位图文件支持三种格式的位图文件:png(首选),jpg(可接受),gif(不建议)。在编译时的资源数据类型,指向 BitmapDrawable 的资源指针。


1.减少图片资源

通常,图标在正常时一种颜色, 在点击时一种颜色。但是,在这种情况下,并不需要使用两张图片。

使用Tint:

    /**
     * @param context 上下文对象
     * @param resId   图片资源
     * @param colorId 颜色资源
     * @return 着色后的Drawable
     */
    public static Drawable getTintDrawable(Context context, @DrawableRes int resId, @ColorRes int colorId) {
        Drawable drawable = AppCompatResources.getDrawable(context, resId);
        ColorStateList colorStateList = ContextCompat.getColorStateList(context, colorId);
        Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
        DrawableCompat.setTintList(wrappedDrawable, colorStateList);
        return wrappedDrawable;
    }
颜色状态资源arrow_back.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorAccent" android:state_enabled="true" android:state_pressed="true"/>
    <item android:color="@android:color/white" android:state_enabled="true"/>
selector>

设置着色后的drawable:

            imageView.setImageDrawable(DrawableUtil.getTintDrawable(this, R.drawable.ic_arrow_back_white, R.color.arrow_back));

效果图下图所示:

Android优化UI(一)_第1张图片

注意:如果ImageView设置没有效果,需要添加:

imageView.setClickable(true);

原因是,当View是可点击的时候,在每一次点击中,它才会将状态改变为”pressed”。

同一张图片多次使用

有时,同一张图片,在不同的页面主题中显示不同的颜色。

使用Tint:

    /**
     * @param drawable       要着色的Drawable
     * @param colorStateList 颜色状态列表
     * @return 着色后的Drawable
     */
    public static Drawable getTintDrawable(Drawable drawable, ColorStateList colorStateList) {
        Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
        DrawableCompat.setTintList(wrappedDrawable, colorStateList);
        return wrappedDrawable;
    }
             imageView.setImageDrawable(DrawableUtil.getTintDrawable(ContextCompat.getDrawable(this, R.drawable.ic_arrow_back_white), ColorStateList.valueOf(Color.RED)));

效果图下图所示:

Android优化UI(一)_第2张图片

也可以使用Drawable的
setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)方法:

     /**
     * @param srcDrawable 要着色的Drawable
     * @param color       着色颜色
     * @return 着色后的Drawable
     */
    public static Drawable getColorDrawable(Drawable srcDrawable, int color) {
        srcDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        return srcDrawable;
    }
              imageView.setImageDrawable(DrawableUtil.getColorDrawable(ContextCompat.getDrawable(this, R.drawable.ic_arrow_back_white), Color.MAGENTA));

效果图如下:

Android优化UI(一)_第3张图片

注意:默认情况下,所有的drawable对象,加载相同的资源会共享状态。如果其中一个对象修改了状态,其它的对象也会收到相同的修改。要避免这种情况,应当设置drawable为mutable:

ContextCompat.getDrawable(this, R.drawable.ic_arrow_back_white).mutate()

这样就可以保证不与其它的drawable共享它的状态。


2.Drawable文件的存放位置

drawable文件的存放目录结构如下所示:

Android优化UI(一)_第4张图片

上面六种不同的drawable文件夹对应着六种不同的屏幕密度,它们的对应关系如下:

  • ldpi:低密度 (ldpi) 屏幕 (~120dpi)
  • mdpi:中密度 (mdpi) 屏幕 (~160dpi)
  • hdpi:高密度 (hdpi) 屏幕 (~240dpi)
  • xhdpi:超高密度 (xhdpi) 屏幕 (~320dpi)
  • xxhdpi:超超高密度 (xxhdpi) 屏幕 (~480dpi)
  • xxxhdpi:超超超高密度 (xxxhdpi) 屏幕 (~640dpi)

这里的屏幕密度指的是:

屏幕物理区域中的像素量;通常称为 dpi(每英寸 点数)。例如, 与“正常”或“高”密度屏幕相比,“低”密度屏幕在给定物理区域的像素较少。

在存放drawable资源时候,不同大小的图片放在不同的drawable-*dpi文件夹下。在一定程度上,设备会根据不同屏幕密度进行不同的缩放:

默认情况下,Android 会缩放位图可绘制对象(.png、.jpg 和 .gif 文件)和九宫格可绘制对象(.9.png 文件),使它们以适当的 物理尺寸显示在每部设备上。例如,如果您的应用只为 基线中密度屏幕 (mdpi) 提供位图可绘制对象,则在高密度 屏幕上会增大位图,在低密度屏幕上会缩小位图。这种缩放可能在 位图中造成伪影。为确保位图的最佳显示效果,应针对 不同屏幕密度加入不同分辨率的替代版本。

那么如果只给了一张图片资源,应该尽量放在适配高密度drawable文件夹下,因为在低密度设备上,即使缩小图片,它的分辨率也会很高,不会容易模糊。反而,如果图片放在低密度drawable文件夹下,在高密度设备上就会进行放大,图片将模糊。

图片在设备上的缩放比例:120:160:240:320:480:640=3:4:6:8:12:16,所以如果放一张96x96的图片在drawable-xhdpi文件夹下时,它在ldpi屏幕上是36x36,mdpi屏幕上是48x48,在hdpi屏幕上是72x72,在xxhdpi屏幕上是144x144,在xxxhdpi屏幕上是192x192。

现在放一张310x220的图片在drawable-xhdpi文件下,它在xxhdpi和xxxdpi屏幕密度上显示的结果如下:

Android优化UI(一)_第5张图片 Android优化UI(一)_第6张图片

由此可见,在xxhdpi屏幕上放大了1.5倍,在xxxhdpi屏幕上放大了2倍。

3.颜色代替图片

有时,背景只是一个单纯色,那么并不需要图片资源,只需要用颜色就可以实现背景的normal和pressed状态。

在/drawable/arrow_back_selector.xml文件中:


<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/colorAccent" android:state_enabled="true" android:state_pressed="true"/>
    <item android:drawable="@android:color/transparent" android:state_enabled="true"/>
selector>

代码设置: imageView.setBackgroundResource(R.drawable.arrwo_back_selector);

效果如下:

Android优化UI(一)_第7张图片


4.圆角图片

在项目中,如果需要使用圆角图片,为了适配问题,不要引入UI设计切好的圆角图片,应使用代码进行圆角裁剪。

        ImageView imageView = (ImageView) findViewById(R.id.image_view);
        Drawable drawable = ContextCompat.getDrawable(this, R.drawable.me);
        RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(),((BitmapDrawable)drawable).getBitmap());
        roundedBitmapDrawable.setCornerRadius(getResources().getDimensionPixelSize(R.dimen.size_2dp));
        roundedBitmapDrawable.setAntiAlias(true);
        imageView.setImageDrawable(roundedBitmapDrawable);

RoundedBitmapDrawable
位于support v4 包的android.support.v4.graphics.drawable中。


参考文档:
1.可绘制对象资源
2.支持多种屏幕

你可能感兴趣的:(图片优化)