Android编程实现自定义ImageView圆图功能的方法
本文实例讲述了Android编程实现自定义ImageView圆图功能的方法。分享给大家供大家参考,具体如下:
首先很感谢开源项目UniversalImageLoader图片加载框架。之前也看过一段时间框架源码,但是却没有时间进行知识点的总结。
今天项目遇到了需要实现圆头像的编辑显示,Universal就已经提供了这个显示RoundedBitmapDisplayer这个类实现了圆图功能。看它的代码可以发现是实现的Drawable
publicstaticclassRoundedDrawableextendsDrawable{
protectedfinalfloatcornerRadius;
protectedfinalintmargin;
protectedfinalRectFmRect=newRectF(),
mBitmapRect;
protectedfinalBitmapShaderbitmapShader;
protectedfinalPaintpaint;
publicRoundedDrawable(Bitmapbitmap,intcornerRadius,intmargin){
this.cornerRadius=cornerRadius;
this.margin=margin;
bitmapShader=newBitmapShader(bitmap,Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
mBitmapRect=newRectF(margin,margin,bitmap.getWidth()-margin,bitmap.getHeight()-margin);
paint=newPaint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
}
@Override
protectedvoidonBoundsChange(Rectbounds){
super.onBoundsChange(bounds);
mRect.set(margin,margin,bounds.width()-margin,bounds.height()-margin);
//Resizetheoriginalbitmaptofitthenewbound
MatrixshaderMatrix=newMatrix();
shaderMatrix.setRectToRect(mBitmapRect,mRect,Matrix.ScaleToFit.FILL);
bitmapShader.setLocalMatrix(shaderMatrix);
}
@Override
publicvoiddraw(Canvascanvas){
canvas.drawRoundRect(mRect,cornerRadius,cornerRadius,paint);
}
@Override
publicintgetOpacity(){
returnPixelFormat.TRANSLUCENT;
}
@Override
publicvoidsetAlpha(intalpha){
paint.setAlpha(alpha);
}
@Override
publicvoidsetColorFilter(ColorFiltercf){
paint.setColorFilter(cf);
}
}
其实总结下来,上面圆图实现步骤就是:
1、通过bitmap初始化位图着色器BitmapShader类
2、计算bitmap原始图片的rect
3、计算放置图片需要的rect
4、使用Matrix类对两个rect进行压缩,然后复制给BitmapShader着色器里去。最后是画布画图。
(刚开始一直以为shader是阴影的意思,原来有道一下是着色器的意思,这个翻译其实对我理解代码还是很重要的,所以不要想当然,要勤奋点,这个是优秀程序员必备要素。)
最后我要实现的是继承ImageView实现圆图
publicclassURoundedImageViewextendsImageView{
privatePaintmBitmapPaint,mBackgroundPaint;
privateBitmapShadermBitmapShader;
privateRectFmBitmapRect,mRect;
privateintborderWidth;
privateBitmapmBitmap;
privateMatrixshaderMatrix;
publicURoundedImageView(Contextcontext,AttributeSetattrs,
intdefStyleAttr){
super(context,attrs,defStyleAttr);
init();
}
publicURoundedImageView(Contextcontext,AttributeSetattrs){
super(context,attrs);
init();
}
publicURoundedImageView(Contextcontext){
super(context);
init();
}
privatevoidinit(){
mBitmapPaint=newPaint();
mBitmapPaint.setAntiAlias(true);
mBackgroundPaint=newPaint();
mBackgroundPaint.setAntiAlias(true);
mBackgroundPaint.setColor(Color.WHITE);
borderWidth=5;
mRect=newRectF();
shaderMatrix=newMatrix();
}
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,
intbottom){
//TODOAuto-generatedmethodstub
super.onLayout(changed,left,top,right,bottom);
}
@Override
protectedvoidonDraw(Canvascanvas){
mBitmap=((BitmapDrawable)getDrawable()).getBitmap();
if(getWidth()==0||getHeight()==0||mBitmap==null){
return;
}
intw=getWidth();
inth=getHeight();
intradius=Math.min(w,h)/2;
canvas.drawCircle(w/2,h/2,radius,mBackgroundPaint);
//传入bitmap初始化位图着色器
if(mBitmapShader==null){
mBitmapShader=newBitmapShader(mBitmap,Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
}
if(mBitmapRect==null){
mBitmapRect=newRectF(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提醒我们Avoidobjectallocationsduringdraw/layoutoperations(preallocateandreuseinstead)这个warning。因为ondraw会不断调用,如果一直new对象的话会吃内存。所以为了避免重复new对象,根据自己的需求进行判空操作。具体根据自己需求来优化代码,有时候为了达到需求也没办法做到在ondraw方法里不出现重复new对象的现象。
总结:多参考优秀的开源项目,用正确的方法做正确的事情!
希望本文所述对大家Android程序设计有所帮助。