Android中的自绘View的那些事儿(六)之 画布裁剪
2017-12-22 10:53
531 查看
我们在之前的文章中有简单介绍过画布Canvas的使用,它可以使用一系列的draw方法来绘制出各种样式的几何的图形、文字和图片来。今天我们继续探讨Canvas的另一种使用,那就是画布裁剪。什么是画布裁剪?它有点像flash 遮罩层的概念,说白了就是把原来一整块画布裁剪部分出来,然后要绘制出来的东西只能在指定的裁剪区域范围内才能显示出来。
restore: 用于恢复Canvas之前保存的状态。也就是使save后对Canvas执行的操作对后续的绘制不会造成影响
clipPath 裁剪路径,就是指在此路径内绘制
clipRect 裁剪矩形,就是指在此矩形内绘制
public MyView(Context context) {
this(context, null, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.iron_man);
canvas.drawBitmap(bitmap, 0, 0, paint);
}
}
我们首先来看下正常情况下,我们只在canvas中绘制一张图片。输出效果:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
canvas.save();
Path path = new Path();
path.addCircle(centerX, centerY, 300, Path.Direction.CW);
canvas.clipPath(path);
canvas.clipRect(centerX - 50, 100, centerX + 50, getHeight() - 100,Region.Op.UNION);
Bitmap bitmap =BitmapFactory.decodeResource(getResources(),R.mipmap.iron_man);
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
}
代码中,我们在开头和结尾分别使用了canvas.save();和canvas.restore();。然后来看中间部分,canvas.clipPath()和canvas.clipRect()两次裁剪了画布。注意clipRect最后的参数Region.Op.UNION,它是表示两个区域叠加。运行效果:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
canvas.save();
Path path = new Path();
path.addCircle(centerX, centerY, 300, Path.Direction.CW);
canvas.clipPath(path);
canvas.clipRect(centerX - 50, 100, centerX + 50, getHeight() - 100,Region.Op.UNION);
canvas.rotate(45, centerX, centerY); // 旋转
canvas.translate(100, 100); // 平移
canvas.scale(0.5f, 0.5f); // 缩放
canvas.skew(0, 1); // 错切
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.iron_man);
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
}
本次代码中,我们加入了旋转(rotate)、平移(translate)、缩放(scale)以及错切(skew)效果。运行效果:
java.lang.UnsupportedOperationException
atandroid.view.GLES20Canvas.clipPath(GLES20Canvas.java:287)
atcom.myapp.MyCustomView.onDraw(SourceFile:288)
at android.view.View.draw(View.java:9310)
at android.view.View.getDisplayList(View.java:8773)
atandroid.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2298)
所以在使用画布裁剪中最好加入捕捉UnsupportedOperationException异常的处理和系统判断过滤。
Canvas的裁剪必须要使用save和restore方法:
save: 用于保存Canvas当前的状态。save之后,我们便可以随意对Canvas进行平移、放缩、旋转、错切、裁剪等操作restore: 用于恢复Canvas之前保存的状态。也就是使save后对Canvas执行的操作对后续的绘制不会造成影响
Canvas的裁剪提供了一些的clip方法:
clipRegion 方法已经不再建议使用clipPath 裁剪路径,就是指在此路径内绘制
clipRect 裁剪矩形,就是指在此矩形内绘制
示例:
public class MyView extends View {public MyView(Context context) {
this(context, null, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.iron_man);
canvas.drawBitmap(bitmap, 0, 0, paint);
}
}
我们首先来看下正常情况下,我们只在canvas中绘制一张图片。输出效果:
修改onDraw代码:
@Overrideprotected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
canvas.save();
Path path = new Path();
path.addCircle(centerX, centerY, 300, Path.Direction.CW);
canvas.clipPath(path);
canvas.clipRect(centerX - 50, 100, centerX + 50, getHeight() - 100,Region.Op.UNION);
Bitmap bitmap =BitmapFactory.decodeResource(getResources(),R.mipmap.iron_man);
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
}
代码中,我们在开头和结尾分别使用了canvas.save();和canvas.restore();。然后来看中间部分,canvas.clipPath()和canvas.clipRect()两次裁剪了画布。注意clipRect最后的参数Region.Op.UNION,它是表示两个区域叠加。运行效果:
再修改onDraw代码:
@Overrideprotected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
canvas.save();
Path path = new Path();
path.addCircle(centerX, centerY, 300, Path.Direction.CW);
canvas.clipPath(path);
canvas.clipRect(centerX - 50, 100, centerX + 50, getHeight() - 100,Region.Op.UNION);
canvas.rotate(45, centerX, centerY); // 旋转
canvas.translate(100, 100); // 平移
canvas.scale(0.5f, 0.5f); // 缩放
canvas.skew(0, 1); // 错切
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.iron_man);
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
}
本次代码中,我们加入了旋转(rotate)、平移(translate)、缩放(scale)以及错切(skew)效果。运行效果:
注意
在Android4.0及之前的手机中,因为硬件加速等原因,在使用clipPath时很有可能会发生UnsupportedOperationException异常,像下面:java.lang.UnsupportedOperationException
atandroid.view.GLES20Canvas.clipPath(GLES20Canvas.java:287)
atcom.myapp.MyCustomView.onDraw(SourceFile:288)
at android.view.View.draw(View.java:9310)
at android.view.View.getDisplayList(View.java:8773)
atandroid.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2298)
所以在使用画布裁剪中最好加入捕捉UnsupportedOperationException异常的处理和系统判断过滤。
相关文章推荐
- Android中的自绘View的那些事儿(四)之 ComposeShader组合渲染器的简介
- Android中的自绘View的那些事儿(七)之 实例分享
- Android中的自绘View的那些事儿(五)之 遮罩滤镜:BlurMaskFilter 和 EmbossMaskFilter 的简介
- Android中的自绘View的那些事儿(八)之 Paint的高级用法
- Android中的自绘View的那些事儿(二)之 Shader渲染器和BitmapShader位图渲染器的简介
- Android中的自绘View的那些事儿(三)之 颜色渐变渲染器:LinearGradient、RadialGradient 和 SweepGradient的简介
- Android中的自绘View的那些事儿(一)
- Android自定义 view之图片裁剪从设计到实现
- Android UI开发专题(四) View自绘控件
- Android之UI学习篇七:ImageView实现适屏和裁剪图片的功能
- Android ImageView实现图片裁剪和显示功能
- android下view的画布和Bitmap及叠加覆盖
- Android 自定义View——使用画布canvas
- Android笔记--简单的自定义View之自绘控件
- Android自定义View之画笔与画布
- Android学习摘记——简单的自定义View(自绘控件)
- Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)
- Android自定义View高级(三)-Canvas之画布操作
- Android之UI学习篇七:ImageView实现适屏和裁剪图片的功能
- Android自定义View之画笔与画布