Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码
程序员文章站
2024-03-04 14:35:59
在android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦。所以在这里写一个自定义圆形imageview,直接去加载网络图片,这样的话就特别的方便...
在android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦。所以在这里写一个自定义圆形imageview,直接去加载网络图片,这样的话就特别的方便。
先上效果图
主要的方法
1.让自定义 circleimageview 继承imageview
/** * 自定义圆形头像 * created by dylan on 2015/11/26 0026. */ public class circleimageview extends imageview { }
2.在构造方法中获取在xml中设置的值
public circleimageview(context context) { super(context); } public circleimageview(context context, attributeset attrs) { this(context, attrs, 0); } public circleimageview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); super.setscaletype(scale_type); /** * 获取在xml中声明的属性 */ typedarray a = context.obtainstyledattributes(attrs, r.styleable.circleimageview, defstyle, 0);//获取xml中的属性 mborderwidth = a.getdimensionpixelsize(r.styleable.circleimageview_border_width, default_border_width); mbordercolor = a.getcolor(r.styleable.circleimageview_border_color, default_border_color); a.recycle(); mready = true; if (msetuppending) { setup(); msetuppending = false; } }
3.初始化各种参数设置
/** * 画圆形图的初始化工作 */ private void setup() { if (!mready) { msetuppending = true; return; } if (mbitmap == null) { return; } /** *调用这个方法来产生一个画有一个位图的渲染器(shader)。 bitmap 在渲染器内使用的位图 tilex the tiling mode for x to draw the bitmap in. 在位图上x方向花砖模式 tiley the tiling mode for y to draw the bitmap in. 在位图上y方向花砖模式 tilemode:(一共有三种) clamp :如果渲染器超出原始边界范围,会复制范围内边缘染色。 repeat :横向和纵向的重复渲染器图片,平铺。 mirror :横向和纵向的重复渲染器图片,这个和repeat 重复方式不一样,他是以镜像方式平铺。 */ mbitmapshader = new bitmapshader(mbitmap, shader.tilemode.clamp, shader.tilemode.clamp); /** * 设置画圆形的画笔 */ mbitmappaint.setantialias(true);//设置抗锯齿 mbitmappaint.setshader(mbitmapshader);//绘制图形时的图形变换 mborderpaint.setstyle(paint.style.stroke); mborderpaint.setantialias(true); mborderpaint.setcolor(mbordercolor); mborderpaint.setstrokewidth(mborderwidth); mbitmapheight = mbitmap.getheight(); mbitmapwidth = mbitmap.getwidth(); /** * 设置边框矩形的坐标 */ mborderrect.set(0, 0, getwidth(), getheight()); /** * 设置边框圆形的半径为图片的宽度和高度的一半的最大值 */ mborderradius = math.max((mborderrect.height() - mborderwidth) / 2, (mborderrect.width() - mborderwidth) / 2); /** * 设置图片矩形的坐标 */ mdrawablerect.set(mborderwidth, mborderwidth, mborderrect.width() - mborderwidth, mborderrect.height() - mborderwidth); /** * 设置图片圆形的半径为图片的宽度和高度的一半的最大值 */ mdrawableradius = math.max(mdrawablerect.height() / 2, mdrawablerect.width() / 2); updateshadermatrix(); /** * 调用ondraw()方法进行绘画 */ invalidate(); } /** * 更新位图渲染 */ private void updateshadermatrix() { float scale; float dx = 0; float dy = 0; /** * 重置 */ mshadermatrix.set(null); /** *计算缩放比,因为如果图片的尺寸超过屏幕,那么就会自动匹配到屏幕的尺寸去显示。 * 确定移动的xy坐标 * */ if (mbitmapwidth * mdrawablerect.height() > mdrawablerect.width() * mbitmapheight) { scale = mdrawablerect.width() / (float) mbitmapwidth; dy = (mdrawablerect.height() - mbitmapheight * scale) * 0.5f; } else { scale = mdrawablerect.height() / (float) mbitmapheight; dx = (mdrawablerect.width() - mbitmapwidth * scale) * 0.5f; } mshadermatrix.setscale(scale, scale); mshadermatrix.posttranslate((int) (dx + 0.5f) + mborderwidth, (int) (dy + 0.5f) + mborderwidth); /** * 设置shader的本地矩阵 */ mbitmapshader.setlocalmatrix(mshadermatrix); }
4.画圆
@override protected void ondraw(canvas canvas) { if (getdrawable() == null) { return; } /** * 画圆形图片 */ canvas.drawcircle(getwidth() / 2, getheight() / 2, mdrawableradius, mbitmappaint); /** * 画圆形边框 */ canvas.drawcircle(getwidth() / 2, getheight() / 2, mborderradius, mborderpaint); }
完整代码,有完整的注释
1.circleimageview 主类
import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmapshader; import android.graphics.canvas; import android.graphics.color; import android.graphics.matrix; import android.graphics.paint; import android.graphics.rectf; import android.graphics.shader; import android.graphics.drawable.bitmapdrawable; import android.graphics.drawable.colordrawable; import android.graphics.drawable.drawable; import android.util.attributeset; import android.widget.imageview; import com.kejiang.yuandl.r; import com.kejiang.yuandl.utils.imagesizeutil; /** * 自定义圆形头像 * created by dylan on 2015/11/26 0026. */ public class circleimageview extends imageview { /** * 圆形头像默认,center_crop!=系统默认的center_crop; * 将图片等比例缩放,让图像的长边边与imageview的边长度相同,短边不够的留空白,缩放后截取圆形部分进行显示。 */ private static final scaletype scale_type = scaletype.center_crop; /** * 图片的压缩质量 * alpha_8就是alpha由8位组成,------alpha_8 代表8位alpha位图 * argb_4444就是由4个4位组成即16位,------argb_4444 代表16位argb位图 * argb_8888就是由4个8位组成即32位,------argb_8888 代表32位argb位图 * rgb_565就是r为5位,g为6位,b为5位共16位,------argb_565 代表8位rgb位图 */ private static final bitmap.config bitmap_config = bitmap.config.argb_8888; /** * 默认colordrawable的宽和高 */ private static final int colordrawable_dimension = 1; /** * 默认边框宽度 */ private static final int default_border_width = 0; /** * 默认边框颜色 */ private static final int default_border_color = color.black; /** * 画图片的矩形 */ private final rectf mdrawablerect = new rectf(); /** * 画边框的矩形 */ private final rectf mborderrect = new rectf(); /** * 对图片进行缩放和移动的矩阵 */ private final matrix mshadermatrix = new matrix(); /** * 画图片的画笔 */ private final paint mbitmappaint = new paint(); /** * 画边框的画笔 */ private final paint mborderpaint = new paint(); /** * 默认边框颜色 */ private int mbordercolor = default_border_color; /** * 默认边框宽度 */ private int mborderwidth = default_border_width; private bitmap mbitmap; /** * 产生一个画有一个位图的渲染器(shader) */ private bitmapshader mbitmapshader; /** * 图片的实际宽度 */ private int mbitmapwidth; /** * 图片实际高度 */ private int mbitmapheight; /** * 图片半径 */ private float mdrawableradius; /** * 边框半径 */ private float mborderradius; /** * 是否初始化准备好 */ private boolean mready; /** * 内边距 */ private boolean msetuppending; public circleimageview(context context) { super(context); } public circleimageview(context context, attributeset attrs) { this(context, attrs, 0); } public circleimageview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); super.setscaletype(scale_type); /** * 获取在xml中声明的属性 */ typedarray a = context.obtainstyledattributes(attrs, r.styleable.circleimageview, defstyle, 0);//获取xml中的属性 mborderwidth = a.getdimensionpixelsize(r.styleable.circleimageview_border_width, default_border_width); mbordercolor = a.getcolor(r.styleable.circleimageview_border_color, default_border_color); a.recycle(); mready = true; if (msetuppending) { setup(); msetuppending = false; } } @override public scaletype getscaletype() { return scale_type; } @override protected void ondraw(canvas canvas) { if (getdrawable() == null) { return; } /** * 画圆形图片 */ canvas.drawcircle(getwidth() / 2, getheight() / 2, mdrawableradius, mbitmappaint); /** * 画圆形边框 */ canvas.drawcircle(getwidth() / 2, getheight() / 2, mborderradius, mborderpaint); } @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(w, h, oldw, oldh); setup(); } /** * 获取边框颜色 * * @return */ public int getbordercolor() { return mbordercolor; } /** * 设置边框颜色 * * @param bordercolor */ public void setbordercolor(int bordercolor) { if (bordercolor == mbordercolor) { return; } mbordercolor = bordercolor; mborderpaint.setcolor(mbordercolor); invalidate(); } /** * 获取边框宽度 * * @return */ public int getborderwidth() { return mborderwidth; } /** * 设置边框宽度 * * @param borderwidth */ public void setborderwidth(int borderwidth) { if (borderwidth == mborderwidth) { return; } mborderwidth = borderwidth; setup(); } /** * 设置资源图片 * * @param bm */ @override public void setimagebitmap(bitmap bm) { super.setimagebitmap(bm); mbitmap = bm; setup(); } /** * 设置资源图片 * * @param drawable */ @override public void setimagedrawable(drawable drawable) { super.setimagedrawable(drawable); mbitmap = getbitmapfromdrawable(drawable); setup(); } /** * 设置资源id * * @param resid */ @override public void setimageresource(int resid) { super.setimageresource(resid); mbitmap = getbitmapfromdrawable(getdrawable()); setup(); } /** * 获取资源图片 * * @param drawable * @return */ private bitmap getbitmapfromdrawable(drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof bitmapdrawable) { return ((bitmapdrawable) drawable).getbitmap(); } try { bitmap bitmap; if (drawable instanceof colordrawable) { bitmap = bitmap.createbitmap(colordrawable_dimension, colordrawable_dimension, bitmap_config); } else { imagesizeutil.imagesize imagesize = imagesizeutil.getimageviewsize(this); bitmap = bitmap.createbitmap(imagesize.width, imagesize.height, bitmap_config); } canvas canvas = new canvas(bitmap); drawable.setbounds(0, 0, canvas.getwidth(), canvas.getheight()); drawable.draw(canvas); return bitmap; } catch (outofmemoryerror e) { return null; } } /** * 画圆形图的方法 */ private void setup() { if (!mready) { msetuppending = true; return; } if (mbitmap == null) { return; } /** *调用这个方法来产生一个画有一个位图的渲染器(shader)。 bitmap 在渲染器内使用的位图 tilex the tiling mode for x to draw the bitmap in. 在位图上x方向花砖模式 tiley the tiling mode for y to draw the bitmap in. 在位图上y方向花砖模式 tilemode:(一共有三种) clamp :如果渲染器超出原始边界范围,会复制范围内边缘染色。 repeat :横向和纵向的重复渲染器图片,平铺。 mirror :横向和纵向的重复渲染器图片,这个和repeat 重复方式不一样,他是以镜像方式平铺。 */ mbitmapshader = new bitmapshader(mbitmap, shader.tilemode.clamp, shader.tilemode.clamp); /** * 设置画圆形的画笔 */ mbitmappaint.setantialias(true);//设置抗锯齿 mbitmappaint.setshader(mbitmapshader);//绘制图形时的图形变换 mborderpaint.setstyle(paint.style.stroke); mborderpaint.setantialias(true); mborderpaint.setcolor(mbordercolor); mborderpaint.setstrokewidth(mborderwidth); mbitmapheight = mbitmap.getheight(); mbitmapwidth = mbitmap.getwidth(); /** * 设置边框矩形的坐标 */ mborderrect.set(0, 0, getwidth(), getheight()); /** * 设置边框圆形的半径为图片的宽度和高度的一半的最大值 */ mborderradius = math.max((mborderrect.height() - mborderwidth) / 2, (mborderrect.width() - mborderwidth) / 2); /** * 设置图片矩形的坐标 */ mdrawablerect.set(mborderwidth, mborderwidth, mborderrect.width() - mborderwidth, mborderrect.height() - mborderwidth); /** * 设置图片圆形的半径为图片的宽度和高度的一半的最大值 */ mdrawableradius = math.max(mdrawablerect.height() / 2, mdrawablerect.width() / 2); updateshadermatrix(); /** * 调用ondraw()方法进行绘画 */ invalidate(); } /** * 更新位图渲染 */ private void updateshadermatrix() { float scale; float dx = 0; float dy = 0; /** * 重置 */ mshadermatrix.set(null); /** *计算缩放比,因为如果图片的尺寸超过屏幕,那么就会自动匹配到屏幕的尺寸去显示。 * 确定移动的xy坐标 * */ if (mbitmapwidth * mdrawablerect.height() > mdrawablerect.width() * mbitmapheight) { scale = mdrawablerect.width() / (float) mbitmapwidth; dy = (mdrawablerect.height() - mbitmapheight * scale) * 0.5f; } else { scale = mdrawablerect.height() / (float) mbitmapheight; dx = (mdrawablerect.width() - mbitmapwidth * scale) * 0.5f; } mshadermatrix.setscale(scale, scale); mshadermatrix.posttranslate((int) (dx + 0.5f) + mborderwidth, (int) (dy + 0.5f) + mborderwidth); /** * 设置shader的本地矩阵 */ mbitmapshader.setlocalmatrix(mshadermatrix); } }
2.里面所使用到的imagesizeutil
public class imagesizeutil { /** * 根据imageview获适当的压缩的宽和高 * * @param imageview * @return */ public static imagesize getimageviewsize(imageview imageview) { imagesize imagesize = new imagesize(); displaymetrics displaymetrics = imageview.getcontext().getresources() .getdisplaymetrics(); layoutparams lp = imageview.getlayoutparams(); int width = imageview.getwidth();// 获取imageview的实际宽度 if (width <= 0) {if(lp!=null){ width = lp.width;// 获取imageview在layout中声明的宽度 } } if (width <= 0) { //width = imageview.getmaxwidth();// 检查最大值 width = getimageviewfieldvalue(imageview, "mmaxwidth"); } if (width <= 0) { width = displaymetrics.widthpixels; } int height = imageview.getheight();// 获取imageview的实际高度 if (height <= 0) {if(lp!=null){ height = lp.height;// 获取imageview在layout中声明的宽度 } } if (height <= 0) { height = getimageviewfieldvalue(imageview, "mmaxheight");// 检查最大值 } if (height <= 0) { height = displaymetrics.heightpixels; } imagesize.width = width; imagesize.height = height; return imagesize; } public static class imagesize { public int width; public int height; } }
用法
布局文件
<com.bulemobi.yuandl.view.circleimageview android:id="@+id/ci" android:layout_width="180dp" android:layout_height="180dp" android:scaletype="centercrop" android:layout_gravity="center_horizontal" app:border_width="1dp" app:border_color="#ff0000" />
activity中的代码,用xutils3加载图片
circleimageview circleimageview= (circleimageview) findviewbyid(r.id.ci); x.image().bind(circleimageview,url,new imageoptions.builder().setimagescaletype(imageview.scaletype.center_crop).build()
以上所述是小编给大家介绍的android 自定义圆形头像circleimageview支持加载网络图片的实现代码,希望对大家有所帮助