欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码

程序员文章站 2024-03-03 16:18:52
在android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦。所以在这里写一个自定义圆形imageview,直接去加载网络图片,这样的话就特别的方便...

在android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦。所以在这里写一个自定义圆形imageview,直接去加载网络图片,这样的话就特别的方便。

先上效果图

Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码

主要的方法

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支持加载网络图片的实现代码,希望对大家有所帮助