自定义ImageView圆图实现

来源:互联网 发布:上海优化公司hxwlkj 编辑:程序博客网 时间:2024/06/05 14:02

首先很感谢开源项目Universal Image Loader图片加载框架。之前也看过一段时间框架源码,但是却没有时间进行知识点的总结。

今天项目遇到了需要实现圆头像的编辑显示,Universal就已经提供了这个显示RoundedBitmapDisplayer这个类实现了圆图功能。看它的代码可以发现是实现的Drawable

public static class RoundedDrawable extends Drawable {protected final float cornerRadius;protected final int margin;protected final RectF mRect = new RectF(),mBitmapRect;protected final BitmapShader bitmapShader;protected final Paint paint;public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) {this.cornerRadius = cornerRadius;this.margin = margin;bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);mBitmapRect = new RectF (margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin);paint = new Paint();paint.setAntiAlias(true);paint.setShader(bitmapShader);}@Overrideprotected void onBoundsChange(Rect bounds) {super.onBoundsChange(bounds);mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin);// Resize the original bitmap to fit the new boundMatrix shaderMatrix = new Matrix();shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);bitmapShader.setLocalMatrix(shaderMatrix);}@Overridepublic void draw(Canvas canvas) {canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint);}@Overridepublic int getOpacity() {return PixelFormat.TRANSLUCENT;}@Overridepublic void setAlpha(int alpha) {paint.setAlpha(alpha);}@Overridepublic void setColorFilter(ColorFilter cf) {paint.setColorFilter(cf);}}

其实总结下来,上面圆图实现步骤就是 1、通过bitmap初始化位图着色器BitmapShader类,2、计算bitmap原始图片的rect,3、计算放置图片需要的rect。4、使用Matrix类对两个rect进行压缩,然后复制给BitmapShader着色器里去。最后是画布画图。(刚开始一直以为shader是阴影的意思,原来有道一下是着色器的意思,这个翻译其实对我理解代码还是很重要的,所以不要想当然,要勤奋点,这个是优秀程序员必备要素。)


最后我要实现的是继承ImageView实现圆图

public class URoundedImageView extends ImageView {private Paint mBitmapPaint,mBackgroundPaint;private BitmapShader mBitmapShader;private RectF mBitmapRect , mRect;private int borderWidth;private Bitmap mBitmap;private Matrix shaderMatrix;public URoundedImageView(Context context, AttributeSet attrs,int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public URoundedImageView(Context context, AttributeSet attrs) {super(context, attrs);init();}public URoundedImageView(Context context) {super(context);init();}private void init(){mBitmapPaint = new Paint();mBitmapPaint.setAntiAlias(true);mBackgroundPaint = new Paint();mBackgroundPaint.setAntiAlias(true);mBackgroundPaint.setColor(Color.WHITE);borderWidth = 5;mRect = new RectF();shaderMatrix = new Matrix();}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {// TODO Auto-generated method stubsuper.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {mBitmap = ((BitmapDrawable) getDrawable()).getBitmap();if (getWidth() == 0 || getHeight() == 0 || mBitmap == null) {return;}int w = getWidth();int h = getHeight();int radius = Math.min(w, h) / 2;canvas.drawCircle(w / 2, h / 2, radius, mBackgroundPaint);//传入bitmap初始化位图着色器if (mBitmapShader == null) {mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);}if (mBitmapRect == null) {mBitmapRect = new RectF(borderWidth, borderWidth,mBitmap.getWidth() - borderWidth, mBitmap.getHeight()- borderWidth);}mBitmapPaint.setShader(mBitmapShader);mRect.set(borderWidth, borderWidth, w - borderWidth, h - borderWidth);//对bitmap原始图进行缩放shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);mBitmapShader.setLocalMatrix(shaderMatrix);canvas.drawRoundRect(mRect, radius, radius, mBitmapPaint);}}

刚开始写的不够规范,直接在ondraw方法里面new一些需要的对象,lint提醒我们Avoid object allocations during draw/layout operations (preallocate and reuse instead)这个warning。因为ondraw会不断调用,如果一直new对象的话会吃内存。所以为了避免重复new对象,根据自己的需求进行判空操作。具体根据自己需求来优化代码,有时候为了达到需求也没办法做到在ondraw方法里不出现重复new对象的现象。


总结:多参考优秀的开源项目,用正确的方法做正确的事情!







0 0