SeniorUI07_Canvas的使用

高级UI汇总​​​​​​​
API:https://developer.android.google.cn/reference/android/graphics/Canvas
##一、Demo
SeniorUI07_CanvasEmployActivity

##二、 什么是Canvas
Canvas:字面意思是画布,其实是封装的一个工具类
The Canvas class holds the “draw” calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).
Canvas的四大要素:

  1. 一个是用来保存像素的bitmap ----- 画板
  2. 一个Canvas在Bitmap上进行绘制操作 ---- 画布或者画纸(Layer—saveLayer操作时,新建一个透明的画布图层)
  3. 绘制的东西
  4. 绘制的画笔Paint

##三、 Canvas的作用

####1 画常见效果:
线(多条线)、点(多个点)、矩形

####2 画圆角路径
(path.addRoundRect(r,raduis,Path.Direction.CCW))、椭圆等

####3 画Region:
区域的意思,表示canvas图层上的一块封闭的区域,用于构造复杂的图形;
#####1) Region的简单使用
Region不能直接绘制,需要使用迭代器遍历

 RectF r = new RectF(100, 100, 400, 500);
 Path path = new Path();
 float radii[] = {10, 10, 10, 10, 10, 10, 50, 60};
 path.addRoundRect(r, radii, Path.Direction.CCW);

 Region region = new Region(100, 100, 400, 500);
 Region region1 = new Region();
 region1.setPath(path, region);

 //结合区域迭代器使用(得到图形里面的所有的矩形区域)
  RegionIterator iterator = new RegionIterator(region1);
  Rect rect = new Rect();
  while (iterator.next(rect)) {
       canvas.drawRect(rect, paint);
  }

#####2 )Region的合成
常见API
合并:region.union()
取交集: region.op(r,Region.Op.UNION(2))
在取合并或取交集的时需要设置模板Op
Region.Op有的几种模式:
DIFFERENCE(0),INTERSECT(1),UNION(2), XOR(3),REVERSE_DIFFERENCE(4),REPLACE(5);
这里写图片描述
使用:

 Rect rect1 = new Rect(100,25,150,175);
        Rect rect2 = new Rect(25,75,200,125);
        canvas.drawRect(rect1,paint);
        canvas.drawRect(rect2,paint);

        canvas.translate(0,200);
        paint.setTextSize(UtilsDensity.dip2px(13));
        canvas.drawText("region.op(region1,region2, Region.Op.XOR)结果:",60,100,paint);
        canvas.translate(0,100);
        Region region1 = new Region(rect1);
        Region region2 = new Region(rect2);

        Region region = new Region();
        region.op(region1,region2, Region.Op.XOR);

        RegionIterator iterator = new RegionIterator(region);
        Rect rect = new Rect();
        while (iterator.next(rect)){
            canvas.drawRect(rect,paint);
        }

##四 Canvas的变换技巧-了解Canas里面的坐标系

Canvas里面牵扯两种坐标系:Canvas自己的坐标系、绘图坐标系

###1 Canvas的坐标系:
它就在View的左上角,做坐标原点往右是X轴正半轴,往下是Y轴的正半轴,有且只有一个,唯一不变

**作用:**有时候改变绘制对象位置比较麻烦,而改变坐标轴位置进行绘制比较简单

平移(canvas.translate)
旋转(canvas.rotate)
缩放(canvas.scale)
斜拉(canvas.skew)
裁剪(canvas.clipRect(new Rect(, , , )); canvas.clipPath())

public class CanvasClipView extends View {

    private Bitmap mBitmap;
    private Rect mRect = new Rect();
    private PaintFlagsDrawFilter pdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG);
    private Paint mPaint = new Paint();
    private Path mPath=new Path();


    public CanvasClipView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CanvasClipView(Context context) {
        this(context,null);
    }


    private void init() {
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);// 抗锯尺
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(mBitmap == null)
        {
            return;
        }
        mRect.set(0,0,getWidth(),getHeight());
        canvas.setDrawFilter(pdf);
        mPath.addCircle(getWidth() / 2, getWidth() /2, getHeight() /2, Path.Direction.CCW);
        canvas.clipPath(mPath, Region.Op.REPLACE);
        canvas.drawBitmap(mBitmap, null, mRect, mPaint);

    }
}

###2 绘图坐标系:
不是唯一不变的,它与Canvas的Matrix有关系,当Matrix发生改变的时候,绘图坐标系对应的进行改变;同时这个过程是不可逆的(save和restore方法来保存和还原变化操作);Matrix又是通过我们设置translate、rotate、scale、skew来进行改变的

##五、 Canvas的状态保存-状态栈、Layer栈

####1 Canvas状态栈
canvas.save():Saves the current matrix and clip onto a private stack
canvas.save、canvas. restore方法来保存和还原变换操作Matrix以及Clip剪裁,也可以通过canvas.restoretoCount直接还原到对应栈的保存状态.
例如,canvas.restore后,canvas的坐标就会恢复到对应save状态下,restoretoCount到低层次的count后,再次restoretoCount到高层次的count不起作用
注意看Log输出:

@Override
    protected void onDraw(Canvas canvas) {
        canvas.save();
        Log.i(TAG, "Current SaveCount = " + canvas.getSaveCount());
        //打印结果:Current SaveCount = 2

        canvas.translate(200, 200);
        RectF rectF = new RectF(0,0,300,300);
        canvas.drawBitmap(mBitmap, null, rectF, mPaint);

        canvas.save();
        Log.i(TAG, "Current SaveCount = " + canvas.getSaveCount());
        //打印结果:Current SaveCount = 3
        canvas.rotate(45);
        canvas.drawBitmap(mBitmap, null, rectF, mPaint);

        canvas.save();
        Log.i(TAG, "Current SaveCount = " + canvas.getSaveCount());
        //打印结果:Current SaveCount = 4
        canvas.rotate(45);
        canvas.drawBitmap(mBitmap, null, rectF, mPaint);

        canvas.restoreToCount(1);
        Log.i(TAG, "Current SaveCount = " + canvas.getSaveCount());
        //打印结果:Current SaveCount =1
        canvas.translate(0, 100);
        canvas.drawBitmap(mBitmap, null, rectF, mPaint);

       canvas.restoreToCount(3);
        Log.i(TAG, "Current SaveCount = " + canvas.getSaveCount());
        //打印结果:Current SaveCount =1
        canvas.drawBitmap(mBitmap, null, rectF, mPaint);
    }

####2 Layer栈
saveLayer()
All drawing calls are directed to a newly allocate offscreen bitmap
saveLayer新建一个透明的图层(离屏Bitmap-离屏缓冲),并且会将saveLayer之前的一些Canvas操作延续过来,后续的绘图操作都在新建的layer上面进行,当我们调用restore 或者 restoreToCount 时 更新到对应的图层和画布上

 RectF rectF = new RectF(0,0,400,500);
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
        paint.setColor(Color.GREEN);

        canvas.drawRect(rectF, paint);
        canvas.translate(50,50);

/*savelayer会重新生成一张画布,savelayer之前canvas位置平移操作会保留到新的layer中,canvas.restore调用后layer会回到layer开始(或对应的saveCount),而不是回到canvas画板的保存状态*/        
canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
        canvas.drawColor(Color.BLUE);
        // 通过drawColor可以发现saveLayer是新建了一个图层,
        // 同时结合Lsn5的16种Xfermode叠加形式Demo可以验证是新建的透明图层
        paint.setColor(Color.YELLOW);
        canvas.drawRect(rectF,paint);
        canvas.restore();

        RectF rectF1 = new RectF(10,10,300,400);
        paint.setColor(Color.RED);
        canvas.drawRect(rectF1,paint);

canvas的坐标系平移操作常用于图形移动不方便,移动画板;layer的坐标系常用于图形的合成操作如Xfermode,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值