@946898963
2019-10-04T16:38:04.000000Z
字数 16925
阅读 1519
Android自定义控件
Android绘图
实现圆形的ImageView最简单的方式可以使用裁剪和CardView来实现,但是裁剪的API只支持在Android 5.0及其以上的设备,所以适配起来可能会有问题,为了省去适配的麻烦,我们可以使用自定义控件的方式来实现圆形的ImageView。
使用画笔Paint去绘制东西,当绘制多个图层叠加的时候,有16中模式。效果如下图。
模式 | 说明 |
---|---|
PorterDuff.Mode.CLEAR | 所有绘制不会绘制到画布上 |
PorterDuff.Mode.SRC | 显示上层绘制图形 |
PorterDuff.Mode.DST | 显示下层绘制图形 |
PorterDuff.Mode.SRC_OVER | 图形叠加,上层盖住下层 |
PorterDuff.Mode.DST_OVER | 图形叠加,下层盖住上层 |
PorterDuff.Mode.SRC_IN | 显示上层交集部分 |
PorterDuff.Mode.DST_IN | 显示下层交集部分 |
PorterDuff.Mode.SRC_OUT | 显示上层非交集部分 |
PorterDuff.Mode.DST_OUT | 显示下层非交集部分 |
PorterDuff.Mode.SRC_ATOP | 显示下层非交集部分和上层交集部分 |
PorterDuff.Mode.DST_ATOP | 显示下层交集部分与上层非交集部分 |
PorterDuff.Mode.XOR | 去除交集部分 |
PorterDuff.Mode.DARKEN | 交集部分颜色加深 |
PorterDuff.Mode.LIGHTEN | 交集部分颜色变亮 |
PorterDuff.Mode.MULTIPLY | 显示交集部分,颜色混合叠加 |
PorterDuff.Mode.SCREEN | 取两图层全部区域,交集部分变为透明色 |
官方demo中主要绘制代码如下:
// mDstB是黄色的圆形图bitmap
// mSrcB是蓝色的矩形图bitmap
canvas.drawBitmap(mDstB, 0, 0, paint);
paint.setXfermode(sModes[i]);
canvas.drawBitmap(mSrcB, 0, 0, paint)
更详细的内容,建议阅读:Paint Xfermode 学习小结。
可以看到在两个绘制图形过程中,添加Xfermode绘制模式,能够改变两个图的叠加效果,我们主要关注一下SrcIn模式,可以看见,用图层叠加的交集去截取mSrcB图,可以利用这个,先绘制一个圆角的图,然后设置绘制模式,接着绘制一个矩形的图,两者一叠加,正好是用圆角图去截取矩形图,矩形图也就是我们的原图片了。
代码如下所示:
public class RoundImageViewA extends ImageView {
private Paint paint = new Paint();
public RoundImageViewA(Context context) {
super(context);
}
public RoundImageViewA(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewA(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
//将newBitmap 转换成圆形
Bitmap circleBitmap = toRoundCorner(newBitmap, 14);
final Rect rect = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
// 重置画笔,不然会留下黑色区域
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rect, rect, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
//裁剪后也可以不进行缩放操作,而是将缩放操作放在最后去做。详情请阅读:https://blog.csdn.net/ydxlt/article/details/80307516
return scaleBitmap(newBitmap);
}
//将头像按比例缩放
private Bitmap scaleBitmap(Bitmap bitmap){
int width = getWidth();
//一定要强转成float 不然有可能因为精度不够 出现 scale为0 的错误
float scale = (float)width/(float)bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
private Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
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(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
大多数情况下,要展示图片的控件(ImageView)的长宽和图片的长宽并不是一致的,甚至长宽比都不一致,所以在拿到一张图片时候,大多数情况下需要根据控件的大小对图片进行拉伸缩放处理,有人会问为什么不直接使用ImageView属性scaleType去控制拉伸缩放,这是因为当我们将一个Bitmap绘制成圆角后,再去进行拉伸缩放,圆角可能会变形,所以在Bitmap设置到控件之前就需要对Bitmap进行一下拉伸缩放处理,直接看下面代码。
// 图片根据控件大小等比例缩放拉伸
float widthScale = imageViewWidth * 1.0f / bitmap.getWidth();
float heightScale = imageViewHeight * 1.0f / bitmap.getHeight();
// 设置长宽拉伸缩放比
Matrix matrix = new Matrix();
matrix.setScale(widthScale, heightScale);
// 拉伸缩放图片
Bitmap newBt = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
拉伸缩放也可以在
Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
方法中控制。
利用这种缩放方式实现了RoundImageViewB,代码如下所示:
public class RoundImageViewB extends ImageView {
private Paint paint = new Paint();
public RoundImageViewB(Context context) {
super(context);
}
public RoundImageViewB(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewB(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
//将newBitmap 转换成圆形
Bitmap circleBitmap = toRoundCorner(newBitmap, 14);
final Rect rectSrc = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
final Rect rectDes = new Rect(0, 0, getWidth(), getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rectSrc, rectDes, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return newBitmap;
}
private Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
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(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
所有的绘制圆角的实现,推荐使用这个方法,不仅仅可以帮助我们实现圆角,连部分圆角都可以实现,比如顶部是两个圆角,底部是两个直角的图片。
首先介绍一下BitmapShader这个类,它作为纹理用于绘制一张图。新图可以是纹理图重复/镜像/边缘像素拉伸而绘制成的新图。这个类构造函数很简单,BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY),第一个参数是Bitmap,作为纹理图传入,tileX是指在水平方向上的绘制方式,tileY是指在竖直方向上的绘制方式。TileMode有三种属性,拉伸、重复、镜像。
使用BitmapShader绘制图的时候,是从画布的左上角开始绘制的。我们是使用拉伸的绘制模式,直接来看一下代码,了解处理过程。
/**
* 圆形控件
*
* @author ljnalex
*
*/
public class RoundImageViewC extends ImageView {
private Paint paint = new Paint();
public RoundImageViewC(Context context) {
super(context);
}
public RoundImageViewC(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewC(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
//将newBitmap 转换成圆形
Bitmap circleBitmap = toRoundCorner(newBitmap, 14);
final Rect rect = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rect, rect, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return scaleBitmap(newBitmap);
}
//将头像按比例缩放
private Bitmap scaleBitmap(Bitmap bitmap){
int width = getWidth();
//一定要强转成float 不然有可能因为精度不够 出现 scale为0 的错误
float scale = (float)width/(float)bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
private Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
// 初始化绘制纹理图
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(output);
// 初始化画笔
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
// 利用画笔将纹理图绘制到画布上面
canvas.drawCircle(bitmap.getWidth()/2,bitmap.getWidth()/2,bitmap.getWidth()/2,paint);
return output;
}
}
首先初始化了绘制的纹理图。然后初始化了画布和画笔,设置画笔绘制的纹理图,画笔在绘制图形时候就不是使用单纯的颜色绘制了。最后在利用画笔在画布上面绘制出圆形图片。
利用Rect实现缩放的RoundImageViewD
/**
* 圆形控件
* @author ljnalex
*/
public class RoundImageViewD extends ImageView {
private Paint paint = new Paint();
public RoundImageViewD(Context context) {
super(context);
}
public RoundImageViewD(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewD(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
//将newBitmap 转换成圆形
Bitmap circleBitmap = toRoundCorner(newBitmap, 14);
final Rect rectSrc = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
final Rect rectDes = new Rect(0, 0, getWidth(), getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rectSrc, rectDes, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return newBitmap;
}
private Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
// 初始化绘制纹理图
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(output);
// 初始化画笔
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
// 利用画笔将纹理图绘制到画布上面
canvas.drawCircle(bitmap.getWidth()/2,bitmap.getWidth()/2,bitmap.getWidth()/2,paint);
return output;
}
}
利用BitmapShader还可以实现很多其他样式的效果,有下面几种:
具体请参考:Android圆角图片和圆形图片实现总结。
关于画布裁剪的知识,建议阅读:Canvas的裁剪。
/**
* 圆形控件
*
* @author zhangyan
*
*/
public class RoundImageViewE extends ImageView {
private Paint paint = new Paint();
public RoundImageViewE(Context context) {
super(context);
}
public RoundImageViewE(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewE(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
//将newBitmap 转换成圆形
Bitmap circleBitmap = toRoundCorner(newBitmap);
final Rect rect = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rect, rect, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return scaleBitmap(newBitmap);
}
//将头像按比例缩放
private Bitmap scaleBitmap(Bitmap bitmap){
int width = getWidth();
//一定要强转成float 不然有可能因为精度不够 出现 scale为0 的错误
float scale = (float)width/(float)bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
private Bitmap toRoundCorner(Bitmap bitmap) {
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(output);
// 初始化画笔
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Path path = new Path();
path.addCircle(bitmap.getWidth()/2, bitmap.getWidth()/2,bitmap.getWidth()/2, Path.Direction.CCW);
canvas.clipPath(path, Region.Op.INTERSECT);
// 利用画笔将纹理图绘制到画布上面
canvas.drawBitmap(bitmap,rect,rect,paint);
return output;
}
}
利用Rect实现缩放的RoundImageViewF。
public class RoundImageViewF extends ImageView {
private Paint paint = new Paint();
public RoundImageViewF(Context context) {
super(context);
}
public RoundImageViewF(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewF(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
Bitmap circleBitmap = toRoundCorner(newBitmap);
final Rect rectSrc = new Rect(0, 0, newBitmap.getWidth(), newBitmap.getHeight());
final Rect rectDes = new Rect(0, 0, getWidth(), getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rectSrc, rectDes, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return newBitmap;
}
private Bitmap toRoundCorner(Bitmap bitmap) {
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(output);
// 初始化画笔
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Path path = new Path();
path.addCircle(bitmap.getWidth()/2, bitmap.getWidth()/2,bitmap.getWidth()/2, Path.Direction.CCW);
canvas.clipPath(path, Region.Op.INTERSECT);
// 利用画笔将纹理图绘制到画布上面
canvas.drawBitmap(bitmap,rect,rect,paint);
return output;
}
}
在面试的过程中阿里的面试官说这种方案会新建一个Bitmap,所以可能会导致内存占用率过高。我们可以改进上面的裁剪的实现方式,直接在原来的画布上进行裁剪,避免创建新的的Bitmap,改进后的代码如下所示:
public class RoundImageViewE extends ImageView {
private Paint paint = new Paint();
public RoundImageViewE(Context context) {
super(context);
}
public RoundImageViewE(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewE(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap circleBitmap = dealRawBitmap(rawBitmap);
Path path = new Path();
path.addCircle(getWidth()/2, getHeight()/2,getWidth()/2, Path.Direction.CCW);
canvas.clipPath(path, Region.Op.INTERSECT);
final Rect rect = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rect, rect, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return scaleBitmap(newBitmap);
}
//将头像按比例缩放
private Bitmap scaleBitmap(Bitmap bitmap){
int width = getWidth();
//一定要强转成float 不然有可能因为精度不够 出现 scale为0 的错误
float scale = (float)width/(float)bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
}
public class RoundImageViewF extends ImageView {
private Paint paint = new Paint();
public RoundImageViewF(Context context) {
super(context);
}
public RoundImageViewF(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundImageViewF(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap circleBitmap = dealRawBitmap(rawBitmap);
Path path = new Path();
path.addCircle(getWidth()/2, getHeight()/2,getWidth()/2, Path.Direction.CCW);
canvas.clipPath(path, Region.Op.INTERSECT);
final Rect rectSrc = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
final Rect rectDes = new Rect(0, 0, getWidth(), getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rectSrc, rectDes, paint);
} else {
super.onDraw(canvas);
}
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return newBitmap;
}
}
Demo链接:ImageViews
参考链接:
【Android】自定义圆形ImageView(圆形头像 可指定大小)(XferMode方式主要参考自这篇文章)
Android自定义圆角矩形ImageView,支持Glide加载图片及颜色填充&&Android圆角图片和圆形图片实现总结(利用Rect对Bitmap进行缩放,参考自这两篇文章)
Android圆角图片和圆形图片实现总结(BitmapShader方式主要参考自这篇文章,这篇文章也详细的介绍了Xfermode的相关知识)
各个击破搞明白PorterDuff.Mode(推荐阅读这个)
Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解
细数PorterDuffXferMode的几个坑, PorterDuffXferMode不正确的真正原因
android中对Canvas.drawCircle()方法的理解
mPaint.setStyle(Paint.Style.STROKE);//空心效果 只会画出圆弧
如果不设置的话,画圆是实心的圆
android canvas void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)