本文实例讲述了Android编程实现自定义ImageView圆图功能的方法。分享给大家供大家参考,具体如下:
首先很感谢开源项目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); } @Override protected 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 bound Matrix shaderMatrix = new Matrix(); shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL); bitmapShader.setLocalMatrix(shaderMatrix); } @Override public void draw(Canvas canvas) { canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint); } @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); } }
其实总结下来,上面圆图实现步骤就是:
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(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // TODO Auto-generated method stub super.onLayout(changed, left, top, right, bottom); } @Override protected 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对象的现象。
总结:多参考优秀的开源项目,用正确的方法做正确的事情!
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。