Android中的自绘View的那些事儿(六)之 画布裁剪

来源:互联网 发布:如何利用淘宝赚钱 编辑:程序博客网 时间:2024/06/04 19:54

我们在之前的文章中有简单介绍过画布Canvas的使用,它可以使用一系列的draw方法来绘制出各种样式的几何的图形、文字和图片来。今天我们继续探讨Canvas的另一种使用,那就是画布裁剪。什么是画布裁剪?它有点像flash 遮罩层的概念,说白了就是把原来一整块画布裁剪部分出来,然后要绘制出来的东西只能在指定的裁剪区域范围内才能显示出来。

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代码:

  @Override   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,它是表示两个区域叠加。运行效果:

再修改onDraw代码:

   @Override   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)效果。运行效果:

注意

在Android4.0及之前的手机中,因为硬件加速等原因,在使用clipPath时很有可能会发生UnsupportedOperationException异常,像下面:

java.lang.UnsupportedOperationExceptionatandroid.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异常的处理和系统判断过滤。


阅读全文
0 0
原创粉丝点击