Android 自定义圆形图片 CircleImageView
1.效果预览
1.1.布局中写自定义圆形图片的路径即可
1.2.然后看一看图片效果
1.3.原图是这样的 @mipmap/ic_launcher
2.使用过程
2.1.CircleImageView源代码
public class CircleImageView extends AppCompatImageView {private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;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;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);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);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;}}@Overridepublic ScaleType getScaleType() {return SCALE_TYPE;}@Overridepublic void setScaleType(ScaleType scaleType) {if (scaleType != SCALE_TYPE) {throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));}}@Overrideprotected void onDraw(Canvas canvas) {if (getDrawable() == null) {return;}canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);setup();}public int getBorderColor() {return mBorderColor;}public void setBorderColor(int borderColor) {if (borderColor == mBorderColor) {return;}mBorderColor = borderColor;mBorderPaint.setColor(mBorderColor);invalidate();}public int getBorderWidth() {return mBorderWidth;}public void setBorderWidth(int borderWidth) {if (borderWidth == mBorderWidth) {return;}mBorderWidth = borderWidth;setup();}@Overridepublic void setImageBitmap(Bitmap bm) {super.setImageBitmap(bm);mBitmap = bm;setup();}@Overridepublic void setImageDrawable(Drawable drawable) {super.setImageDrawable(drawable);mBitmap = getBitmapFromDrawable(drawable);setup();}@Overridepublic void setImageResource(int resId) {super.setImageResource(resId);mBitmap = getBitmapFromDrawable(getDrawable());setup();}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 {bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), 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;}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.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);updateShaderMatrix();invalidate();}private void updateShaderMatrix() {float scale;float dx = 0;float dy = 0;mShaderMatrix.set(null);if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {scale = mDrawableRect.height() / mBitmapHeight;dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;} else {scale = mDrawableRect.width() / mBitmapWidth;dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;}mShaderMatrix.setScale(scale, scale);mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);mBitmapShader.setLocalMatrix(mShaderMatrix);}}
View Code
2.2.在values中新建一个资源文件==>attrs_CircleImageView.xml
<resources><!-- 圆形头像 --><declare-styleable name="CircleImageView"><attr name="border_width" format="dimension" /><attr name="border_color" format="color" /></declare-styleable></resources>
View Code
2.3.布局中将ImageView视图换成自定义类,路径写自己的
2.4.大功告成!然后图片就乖乖地变成圆形了。如果想了解源码,请看下方的分析。
3.CircleImageView源代码分析
3.1.成员变量分析
ScaleType是图片显示方式。可以参考一下这篇文章了解ScaleType。
可以有八种取值方式:
①.matrix==>表示原图从ImageView的左上角开始绘制。
②.fitXY==>填充整个ImageView,需要对图片进行一些缩放,会变形。
③.fitStart==>按比例缩放至View的宽度或者高度(取最小值),然后居上或者居左显示。
④.fitCenter==>将图片按比例缩放之后居中显示。
⑤.fitEnd==>按比例缩放之后居右或者居下显示。
⑥.center==>将原图按照原来的大小居中显示,如果超出ImageView的大小,剪裁掉多余的部分。
⑦.centerCrop==>将ImageView填充满,按照比例缩放原图,多余的宽和高裁剪掉,最常用的。
⑧.centerInside==>将原图完整的显示出来,按照比例缩放原图,一般都变得很小了。
Bitmap.Config是什么东西呢?可以参考一下这篇文章了解Bitmap.Config。
其实这都是色彩的存储方法,我们知道ARGB指的是一种色彩模式。
里面A代表Alpha,R表示Red,G表示Green,B表示Blue。每个原色都存储着所表示的颜色的信息值。
位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真。
这里定义了一个COLORDEAWABLE_DIMESION用来干什么呢?
然后又定义了一个DEFAULT_BORDER_WIDTH,用来干啥呢?
首先了解一下TypedArray,参考一下这篇文章。
首先需要有一个资源文件,就是自定义的视图布局,这里是attrs_CircleImageView.xml
然后这里用到了DEFAULT_BORDER_WIDTH了。
了解一下RectF,参考一下这篇文章了解RectF。
RectF类和Rect类似,但是RectF参数是传的Float,所以尾巴有个F了。
可以参考一下这篇文章了解Matrix。
这其实就是一个三维矩阵。
然后主要作用分成4块。
用到的方法有:
postTranslate是指在setScale后平移。
由于缩放是以(0,0)为中心,所以为了把界面的中心与(0,0)对齐,调用postTranslate(centerX,centerY)把
图片向这(x,y)方向移动。
什么是Paint类呢?参考这篇文章详细了解。
这个类可以画集合图形,文本和Bitmap。
什么是BitmapShader呢?参考这篇文章详细了解。
就是处理图片渲染的。可以做到这样的效果。
然后定义了两个整型数据,两个浮点型,两个boolean型,之后再分析作用。
3.2.构造函数分析
一个参数的构造函数
两个参数的构造函数
三个参数的构造函数
这个是最关键的一个构造函数了。
将资源文件中的宽度和颜色获取到。
然后调用setup()函数进行初始化。
3.3.重写函数getScaleType
3.4.重写函数setScaleType
3.5.重写onDraw
这里用canvas画了两个圆。
android中对于Canvas.drawCircle()方法不理解的可以参考这篇文章。
3.6.重写onSizeChanged
3.7.边界颜色
3.8.边界宽度
调用了自己写的一个setup()函数。
3.9.重写setImageBitmap
调用了自己写的一个setup()函数。
3.10.重写setImageDrawable
调用了自己写的一个setup()函数。
3.11.重写setImageResource
调用了自己写的一个setup()函数。
3.12.将Drawable转换成Bitmap
3.13.自己写的setup函数
3.14.更新渲染
4.其他自定义圆形图片
4.1.Android开发之自定义圆形的ImageView的实现
效果如下:
自定类代码如下:
/*** 自定义的圆形ImageView,可以直接当组件在布局中使用。* @author caizhiming**/ public class XCRoundImageView extends ImageView{private Paint paint ;public XCRoundImageView(Context context) { this(context,null); } public XCRoundImageView(Context context, AttributeSet attrs) { this(context, attrs,0); } public XCRoundImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); paint = new Paint();} /*** 绘制圆形图片* @author caizhiming*/@Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (null != drawable) { Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); Bitmap b = getCircleBitmap(bitmap, 14); final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight()); final Rect rectDest = new Rect(0,0,getWidth(),getHeight());paint.reset(); canvas.drawBitmap(b, rectSrc, rectDest, paint); } else { super.onDraw(canvas); } } /*** 获取圆形图片方法* @param bitmap* @param pixels* @return Bitmap* @author caizhiming*/private Bitmap getCircleBitmap(Bitmap bitmap, int pixels) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242;final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); int x = bitmap.getWidth(); canvas.drawCircle(x / 2, x / 2, x / 2, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } }
View Code
4.2.第三方库圆形头像CircleImageView的使用
效果如下:
用法如下:
4.3.自定义ImageView系列——简单圆形图片
效果如下:
源代码:
public class CircleImageView extends ImageView {//基本的三个构造函数public CircleImageView(Context context) {super(context);}public CircleImageView(Context context, AttributeSet attrs) {super(context, attrs);}public CircleImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}//自定义View实现过程中很重要的onDraw绘制图形的方法 @Overrideprotected void onDraw(Canvas canvas) {Drawable drawable = getDrawable();//空值判断,必要步骤,避免由于没有设置src导致的异常错误if (drawable == null) {return;}//必要步骤,避免由于初始化之前导致的异常错误if (getWidth() == 0 || getHeight() == 0) {return;}if (!(drawable instanceof BitmapDrawable)) {return;}Bitmap b = ((BitmapDrawable) drawable).getBitmap();if (null == b) {return;}Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);int w = getWidth();Bitmap roundBitmap = getCroppedBitmap(bitmap, w);canvas.drawBitmap(roundBitmap, 0, 0, null);}/*** 初始Bitmap对象的缩放裁剪过程* @param bmp 初始Bitmap对象* @param radius 圆形图片直径大小* @return 返回一个圆形的缩放裁剪过后的Bitmap对象*/public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {Bitmap sbmp;//比较初始Bitmap宽高和给定的圆形直径,判断是否需要缩放裁剪Bitmap对象if (bmp.getWidth() != radius || bmp.getHeight() != radius)sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);elsesbmp = bmp;Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),Config.ARGB_8888);Canvas canvas = new Canvas(output);final Paint paint = new Paint();final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());paint.setAntiAlias(true);paint.setFilterBitmap(true);paint.setDither(true);canvas.drawARGB(0, 0, 0, 0);paint.setColor(Color.parseColor("#BAB399"));canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f,sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);//核心部分,设置两张图片的相交模式,在这里就是上面绘制的Circle和下面绘制的Bitmappaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));canvas.drawBitmap(sbmp, rect, rect, paint);return output;}}
View Code
转载于:https://www.cnblogs.com/Jason-Jan/p/7919311.html
Android 自定义圆形图片 CircleImageView相关推荐
- Android 自定义圆形图片
代码注释很多,简单说下思路,然后直接贴代码 1.截取选定图片中间区域(宽等于高的正方形) 2.按照控件大小进行缩放 3.画圆,设置paint.setXfermode(new PorterDuffXfe ...
- android 自定义圆形图片素材,Android 使用shape制作drawable素材
Android开发中,资源文件中会有大量的图片素材文件,这样会额外增加APP的大小,有时面对对APP 大小有限制的,那就要考虑尽可能的对图片进行压缩处理或者减少资源文件中图片的数量,那么减少了资源素材 ...
- Android实现圆形图片
一.概述 圆形图片现在越来越多应用于Android应用中, 但是用的最多的地方当属于, 头像的显示. 比如QQ, 新浪微博,微信中很多地方都是用了圆形头像,所以有必要深究一下. 二.圆形图片的实现方式 ...
- android自定义控件圆形图片
属性: <com.example.mywechat11.MyCircleImageViewandroid:id="@+id/friend_head"android:layo ...
- Android自定义圆形进度条
Android自定义圆形进度条 github地址:https://github.com/opq1289/CircleProgressView 效果图: 无动画: 有动画: 整圆: 切割圆: 具体步骤: ...
- 鸿蒙os事例代码,鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码
一.背景 在采用Java配合xml布局编写鸿蒙app页面的时候,发现sdk自带的Image组件并不能将图片设置成圆形,反复了翻阅了官方API手册(主要查阅了Compont和Image相关的API),起 ...
- Kotlin实战练习——自定义圆形图片三种实现方式
Kotlin实战练习--自定义圆形图片三种实现方式 前言 如今Kotlin越来越重要,本人也开始了Kotlin的学习.为了检测学习效果,加深学习印象,同时回顾一下以前的一些知识点,决定从写一个自定义圆 ...
- Unity 自定义圆形图片
使用Mask组件的缺点 我们知道项目中可以这样展示圆形图片,一般是Image组件,下面再加上一个圆形Mask.但是这样做有几个缺点: 使用Mask会额外消耗多一个Drawcall来创建Mask,做像素 ...
- Android 圆形图片 CircleImageView(Xfermode方式)
Android中实现圆形图片,总的说来有2种方法. Xfermode方式,就是本文要讲的实现方式. BitmapShader(着色器)和Matrix(矩阵)方式 第二种实现方式的代表作,就是Henni ...
最新文章
- [转] CSS 颜色名
- 百度地图api 去左下角百度地图logo的方法
- NuGet学习笔记(2) 使用图形化界面打包自己的类库[转]
- Django实现一个简单的中间件,不熟悉中间件的爬坑之路
- java转json数组对象_java对象转json、json数组 、xml | 学步园
- Linux系统的日志服务器syslogd
- Flash Player9.0 跟Flash Player8.0区别
- ORACLE的Copy命令和create table,insert into的比较
- 每日一题 字典序的第K小数字
- 以太坊的POS共识机制友善的小精灵 Casper
- 手输Unicode字符的方法
- 在OBS中解决无法录制chrome的问题
- Python量化数据获取:总资产同比增长率与净资产同比增长率
- c语言中双引号是什么作用,C语言中单引号与双引号的区别
- c语言水王争霸链表,水王争霸(water)
- SpringCloud极简入门(三)服务提供者与消费者
- feign扫描_Feign基础入门及特性讲解
- 大数据论文_02_MapReduce(个人总结)
- Beta冲刺-第一天
- go test 单元函数测试
热门文章
- 简单图文配置golang+vscode【win10/centos7+golang helloworld+解决install failed等情况】
- leetcode Longest Substring with At Most Two Distinct Characters 滑动窗口法
- 【C/S语言】.net平台
- 数据库 user schema sqlserver 关系
- Python机器学习——DBSCAN聚类
- G6实现标签拖动连线画流程图
- 合肥工业大学—SQL Server数据库实验八:使用聚集函数的SELECT语句
- 2021年大数据Flink(二十八):Flink 容错机制 自动重启策略和恢复
- Python:urllib2模块的基本使用
- CentOS7在防火墙开启与关闭以及端口操作