ImageLoader源码解析(四) 补充 Displayer的实现

来源:互联网 发布:网络摄像头如何修改ip 编辑:程序博客网 时间:2024/06/05 20:54

ImageLoader源码解析(四) 补充 Displayer的实现

1 前言

一般来说,如果说到原型图片,或者边框,或者特别形状的图片处理,那么我们可能第一个想到的是 自定义ImageView去处理,在draw方法里写我们的逻辑
这篇文章说一下除了自定义ImageView的另外一种处理,那就是自定义一个Drawable,
这就是ImageLoader中提供的displayer的对于图片转换的解决方案

2 基础知识

  • Drawable
  • paint
  • BitmapShader
  • Bitmap
  • Matrix
  • 自定义View涉及到的Pain,Rect,Canvas等,如果对自定义View不了解,建议去看下自定义View,主要是绘制那块的处理,其实自定义Drawable和自定义View真的很像

3 解析

Imageloader中提供的有很多,最常用的,就是圆形,弧形的处理了,我们来看这两个是怎么写的

3.1 CircleBitmapDisplayer圆形Drawable

public class CircleBitmapDisplayer implements BitmapDisplayer {    /**     * 边框的颜色     */    protected final Integer strokeColor;    /**     * 边框宽度     */    protected final float strokeWidth;    public CircleBitmapDisplayer() {        this(null);    }    public CircleBitmapDisplayer(Integer strokeColor) {        this(strokeColor, 0);    }    public CircleBitmapDisplayer(Integer strokeColor, float strokeWidth) {        this.strokeColor = strokeColor;        this.strokeWidth = strokeWidth;    }    @Override    public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {        if (!(imageAware instanceof ImageViewAware)) {            throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected.");        }        imageAware.setImageDrawable(new CircleDrawable(bitmap, strokeColor, strokeWidth));    }    public static class CircleDrawable extends Drawable {        /**         * 弧度         */        protected float radius;        /**         * 绘制范围         */        protected final RectF mRect = new RectF();        /**         * bitmap范围         */        protected final RectF mBitmapRect;        protected final BitmapShader bitmapShader;        /**         * 图形画笔         */        protected final Paint paint;        /**         * 边框画笔         */        protected final Paint strokePaint;        /**         * 边框宽度         */        protected final float strokeWidth;        /**         * 边框的弧度         */        protected float strokeRadius;        public CircleDrawable(Bitmap bitmap, Integer strokeColor, float strokeWidth) {            radius = Math.min(bitmap.getWidth(), bitmap.getHeight()) / 2;            bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);            mBitmapRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());            paint = new Paint();            //设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。但是效果更好            paint.setAntiAlias(true);            paint.setShader(bitmapShader);            //如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示速度            paint.setFilterBitmap(true);            //设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰            paint.setDither(true);            //如果边框颜色设置了,那么就有边框            if (strokeColor == null) {                strokePaint = null;            } else {                strokePaint = new Paint();                strokePaint.setStyle(Paint.Style.STROKE);                strokePaint.setColor(strokeColor);                strokePaint.setStrokeWidth(strokeWidth);                strokePaint.setAntiAlias(true);            }            this.strokeWidth = strokeWidth;            strokeRadius = radius - strokeWidth / 2;        }        /**         * 范围发生变化时,可能如果imagview大小发生变化,这里会调用吧         *         * @param bounds         */        @Override        protected void onBoundsChange(Rect bounds) {            super.onBoundsChange(bounds);            mRect.set(0, 0, bounds.width(), bounds.height());            radius = Math.min(bounds.width(), bounds.height()) / 2;            strokeRadius = radius - strokeWidth / 2;            //重新设置bitmap的大小去适应新的绘制范围,这里其实就是fitxy处理            Matrix shaderMatrix = new Matrix();            /**             * 设置变换规则,自动计算mBitmapRect->mRect变换的规则<br/>             * 第三个参数,有FILL,start,end,center,还记得,ImageView的ScaleType吗,对比理解<br/>             * Fill就是FitXY             */            shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);            //为bitmapshader设置变换矩阵            bitmapShader.setLocalMatrix(shaderMatrix);        }        @Override        public void draw(Canvas canvas) {            //绘制bitmap            canvas.drawCircle(radius, radius, radius, paint);            if (strokePaint != null) {                //绘制边框                canvas.drawCircle(radius, radius, strokeRadius, strokePaint);            }        }        //-------------------------下面是通过设置画笔,然后重绘,来支持View的一些设置(透明度,颜色过滤,也可以添加其他的属性支持)-------------------------------        /**         * 获取透明度的格式,看一下父类中的注释         * {@link Drawable#getOpacity() }         * <p>         * 只有四个返回值         * {@link android.graphics.PixelFormat}:         * {@linkplain android.graphics.PixelFormat#UNKNOWN 未知},         * {@linkplain android.graphics.PixelFormat#TRANSLUCENT 系统选择支持半透明的格式 bits},         * {@linkplain android.graphics.PixelFormat#TRANSPARENT 系统选择支持透明度的格式 0-1 }, or         * {@linkplain android.graphics.PixelFormat#OPAQUE 系统选择不透明格式(不需要alpha位)}.         *         * @return         */        @Override        public int getOpacity() {            //系统选择支持半透明的格式            return PixelFormat.TRANSLUCENT;        }        @Override        public void setAlpha(int alpha) {            paint.setAlpha(alpha);        }        @Override        public void setColorFilter(ColorFilter cf) {            paint.setColorFilter(cf);        }    }}

注释很详细了,其实自定义Drawable,很像自定义一个View,我没有看过View的源码,现在让我怀疑View中其实操控的也是绘制一个Drawable,然后将Drawable显示到View中

3.2 RoundedBitmapDisplayer 弧形图像绘制

@Override        public void draw(Canvas canvas) {            //貌似唯一有变化的就是这里了吧,DrawCircle变成了Round            canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint);        }

4 参考

Android 自定义Drawable
http://www.cnblogs.com/a284628487/p/5204170.html

http://blog.csdn.net/lmj623565791/article/details/43752383

Matrix:
http://blog.csdn.net/flash129/article/details/8234599

5 解析源码

https://github.com/yizeliang/Android-Universal-Image-Loader

原创粉丝点击