[TOC]
概述
这是一个可以设置成圆角或者圆角矩形的ImageView,并且可以设置是否支持多点触控放大,缩小,旋转图片,双击放大缩小的自定义的控件。还有一个仿刮刮卡效果的自定义View。
效果展示
效果展示
录制的视频5.4M,可能打不开得下下来看。
相关知识点
-
android matrix 最全方法详解与进阶(完整篇)
这里用于图形变换如:放大缩小,平移,旋转 -
Android的事件分发机制
这里用于解决ImageView与ViewPager嵌套时的事件冲突 -
xFermode的原理及使用
这里用于设置ImageView内图片的形状:圆形和圆角矩形
还有自定义View的刮刮卡效果 -
GestureDetector与ScaleGestureDetector入门
Google的扩展的手势监听api - 其他(来不及了,要开车了!默认你懂了)
上一次我们讲了:Android自定义ImageView(上)之多点触控放大缩小,双击放大缩小
这回,我们在来唠唠:怎么实现圆形或者圆角矩形的Imageiew。让ImageView显示一张圆形图片的方法有很多:让UI切一个,用第三方图片加载框架,直接在xml中设置ImageView控件的形状。这些都可以做到,但是我们需要的是更强大的,扩展性更强的方式。需要不管是什么样的图片,放到控件里面都会变成圆形,圆角矩形,甚至是三角形,五角星等等可定制的控件。嗯,这篇文章讲的就是这样的ImageView。
额,装X好累。直接开始吧。
关键代码和注意事项
思路
1.获取ImageView的图片资源,创建一个Canvas画一个你想要的形状
/**
* 获取圆形图片方法
*
* @param bitmap
* @return Bitmap
* @author caizhiming
*/
private Bitmap getCircleBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
//将output作为canvas的操作对象
canvas.drawCircle(getMatrixRectF().centerX(), getMatrixRectF().centerY(), Math.min(output.getWidth(), output.getHeight()) / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, matrix, paint);
return output;
}
/**
* 获取圆角矩形图片
*/
private Bitmap getBoundsBitmap(Bitmap bitmap, int radius) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
//将output作为canvas的操作对象
canvas.drawRoundRect(getMatrixRectF(), radius, radius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, matrix, paint);
return output;
}
/**
* 在代码中设置图片调用这个,在xml设置图片不调用这个方法
* @param drawable
*/
@Override
public void setImageDrawable(@Nullable Drawable drawable) {
super.setImageDrawable(drawable);
if (isCircle) {
isBounds = false;
Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
paint = new Paint();
outBitmap = getCircleBitmap(bitmap);
postInvalidate();
}
if (isBounds) {
isCircle = false;
Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
paint = new Paint();
outBitmap = getBoundsBitmap(bitmap, radius);
postInvalidate();
}
}
这里面有一个小坑,就是如果在代码中设置图片,那么 ((BitmapDrawable) getDrawable()).getBitmap();是取不到图片的,得重写setImageDrawable()方法,同理,如果在xml中设置了图片,那么是不会执行setImageDrawable()方法,所以获取图片资源的方法两个地方都要写。
2.用Xfermode的(src_in)属性的paint在ondraw()中把bitmap画出来
android.graphics.PorterDuff.Mode.SRC_IN:只在源图像和目标图像相交的地方绘制源图像
@Override
protected void onDraw(Canvas canvas) {
paint.reset();
canvas.drawBitmap(outBitmap, matrix, paint);
}
这里注意重置一下画笔,就这样就完成了,是不是很简单-
总结
不知大家发现没有,我们getCircleBitmap()方法中的Canvas对象CA和ondraw()的canvas对象CB不一样啊。而且ondraw()的canvas画的貌似只是一个空白的bitmap而已啊,怎么会这样呢。
请注意我们实例化我们getCircleBitmap()方法中的Canvas对象时传入的参数 Canvas canvas = new Canvas(output);这个output就是ondraw()中的canvas所画的那个bitmap,这说明getCircleBitmap()中canvas所做的所有的操作都会作用在output上。
还要注意一点canvas不能直接操作资源文件,不然会报错。
项目地址链接
个人公众号
不只是技术文章哦,快关注我吧。
搜索公众号:kedasay
网友评论