Android自定义View之绘制圆形头像功能
作者:黄林晴 发布时间:2022-09-27 19:24:29
前言
做APP应用开发的时候,用户头像肯定是必不可少的,但是90%以上的需求头像都是圆形的。那么,如何通过自定义View的方式实现圆形头像呢,那么,本片博文会告诉你不仅仅是实现过程。一定会有意想不到的收获哦!
最终效果
国际惯例,我们先来看最终实现的效果图
自定义RoundImageView继承自ImageView
public class RoundImageView extends ImageView {
public RoundImageView(Context context) {
super(context);
}
public RoundImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public RoundImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
不知你是否注意过每当我们继承自View的时候,系统都会提示我们覆盖重写4个构造方法,这里我们只覆盖了三个,然后就开始在每个构造方法中进行初始化,那么,是不是每次都会调用所有的构造方法呢,如果不是,这三个构造方法又会什么时候调用呢?下面我们来通过例子来验证。
使用自定义View无非就两种情况下,第一种就是直接在xml布局中使用,另一种就是在Activity中new出来,下面我们分别使用上述两种方式,为了便于观察我们在三个构造方法中分别加入一行打印。
首先我们在xml直接使用,运行打印如下:
com.example.roundimageview D/RoundImageView: RoundImageView: 两个参数的构造方法
然后我们在Activity中,new一个RoundImageView
roundImageView = RoundImageView(this@MainActivity)
roundImageView = RoundImageView(this@MainActivity, null)
roundImageView = RoundImageView(this@MainActivity, null,0)
运行打印日志如下:
结论:自定义View当在xml中使用,使用的是第二个构造方法,当在Activity中使用时,实例化时传入几个参数调用的就是含有几个参数的构造方法。
实现圆形头像的思想
我始终认为自定义View的难度只在于它的实现思想,通常我们遇到问题的时候,并不是Google不到,而是压根就不知道这个问题该去如何Google,如果知道了问题所产生的原因,其实问题已经迎刃而解了,最怕的是不知道问题为什么会产生。
实现圆形头像的思想一个简单的图就可以表示了。
矩形区域是完整的图片,圆形区域就是我们最终显示的头像区域,那么就很简单了,圆形区域与矩形区域相交,取并集区域?在矩形中画一个与矩形长或宽相切的圆,而圆的直径是长或宽较短的一边。
编码实现
获取原有头像的bitmap
首先我们需要获取设置头像的bitmap,我们可以直接通过API来获取设置的图片资源,
drawable = this.getDrawable();
再将图片资源转化为bitmap
首先我们判断drawable是否为空,如果为空说明用户没有设置,抛出资源未找到的异常。
if (drawable == null) {
throw new Resources.NotFoundException("Image resource not set");
}
如果不为空,我们创建一个与图片资源大小相等的bitmap,并将bitmap绘制出来,代码如下所示:
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight());
drawable.draw(canvas);
绘制圆形bitmap
通过上面的代码,我们得到了原有的bitmap图像,紧接着我们需要绘制圆形的bitmap,与上面类似,首先创建一个和bitmap大小一致的位图
circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
我们画一个与bitmap等大的矩形
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawRect(rect,paint);
RectF rectF = new RectF(rect);
将较短的一边设置圆的半径
float roundRa = 0.0f;
if (bitmap.getWidth() > bitmap.getHeight()) {
roundRa = bitmap.getHeight() / 2.0f;
} else {
roundRa = bitmap.getWidth() / 2.0f;
}
设置paint和canvas属性
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.WHITE);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawARGB将绘制裁剪设为透明,paint.setXfermode
中的PorterDuffXfermode
类很强大,后面我们会单独一篇文章讲解。
最终我们重新将bitmap绘制出来即可
canvas.drawBitmap(bitmap, rect, rect, paint);
绘制部分完整代码如下所示:
* 获取圆形裁剪的bitmap
*
* @param bitmap 原bitmap
*/
private Bitmap getCircleBitmap(Bitmap bitmap) {
circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(circleBitmap);
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
RectF rectF = new RectF(rect);
float roundRa = 0.0f;
if (bitmap.getWidth() > bitmap.getHeight()) {
roundRa = bitmap.getHeight() / 2.0f;
} else {
roundRa = bitmap.getWidth() / 2.0f;
}
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.GRAY);
canvas.drawRoundRect(rectF, roundRa, roundRa, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return circleBitmap;
}
设置最终的bitmap
得到bitma后我们直接重新设置即可显示
setImageBitmap(getCircleBitmap(bitmap));
本实例较为简单,就不贴所有代码了,如有需要留言邮箱即可,如有纰漏之处,欢迎指正!晚安!
9.15 22:17 更新
代码已上传github:https://github.com/huanglinqing123/RoundImageView
总结
以上所述是小编给大家介绍的Android自定义View之绘制圆形头像功能,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://blog.csdn.net/huangliniqng/article/details/100813623


猜你喜欢
- 很不错的手电筒APP,分享给大家,希望大家喜欢。1. Java代码 package com.
- mybatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“val
- 分析代码规范,并从代码角度分析存在的风险,并且支持一键更改。具体操作如下图:简单方便,最主要的是好用!补充:下面看下IntelliJ IDE
- 起因:有后端同事反馈在异步线程中获取了request中的参数,然后下一个请求是get请求的话,发现会偶尔出现参数丢失的问题.示例代码:@Ge
- 引言:在使用循环的时候,循环里面带有break、continue、return的时候经常弄混,今天特意整理了下,以待后用... f
- 前言当初年少懵懂,那年夏天填志愿选专业,父母听其他长辈说选择计算机专业好。从那以后,我的身上就有了计院深深的烙印。从寝室到机房,从机房到图书
- 本文介绍了Android 删除所有build编译文件,翻译磁盘空间,分享给大家,也给自己留个笔记,具体如下: public static v
- 由于ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以会警告&
- Android 捕获运行时异常详解Android 异常分为两类:CheckedException 和 UnCheckedExceptionC
- 前言前段时间因为工作的需要用到Spring事件,翻翻文档将功能实现了,但是存在少许理解不畅的地方,今天有空来梳理梳理。需求背景叶子同学在新入
- 1.鼠标右击我的电脑–》属性–》高级系统设置2.把下面的变量名称和电脑文件的本地路径填进去即可(注意:变量值后面后面不要带分号)jdk环境变
- C# 操作符之三元操作符“?:”是什么呢?C# 操作符之三元操作符“?:”有时也称为条件操作符。对条件表达式b?x:y,先计算条件b,然后进
- 一、简介在Spring中,有这么2个接口:BeanFactory和FactoryBean,名字很相似,很多小伙伴经常混淆,在面试的时候也经常
- 1.顺
- Android 倒计时一般实现方式:handler+postDelayed() 方式Timer + TimerTask + handler
- Maven是项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。Maven是一个项目管理工具,它包
- 之前的一篇文章中的代码中有一个using的用法,刚开始查看了一些资料说是强制关闭对象的一个命令。今天又查了一些资料,才明白,原来using指
- Java反射详解本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,
- 本文介绍MediaPlayer的使用。MediaPlayer可以播放音频和视频,另外也可以通过VideoView来播放视频,虽然VideoV
- 一)URL代理请求 该方式请求有两种代理方式。方式一:使用该方式代理之后,之后的所有接口都会使用代理请求// 对http开启全局代理Syst