本文实例讲述了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程序设计有所帮助。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐