Android draw学习

前言


公司最近项目不算很忙,一直想看看andorid中draw的流程,想深入理解下这个东西怎么用,于是也是看博客,看鸿神,主席的博客,想来做出点东西自己也顺便记录下自己学习的过程吧,好了,不多说,有句话怎么说,talk is cheap,show me the code!


实现步骤


老生常谈,android 中自定义View 无非就是这三个步骤:

Measure(测量,根据测量规格MesureSpec,不会的看大神博客吧),onLayout一般是自定义Group,自定义Layout,如果子元素需要重新布局,则需重写该方法,最后就是onDraw了,使用画笔Paint在画布Canvas上肆意挥洒吧,今天我就带大家简单的画出圆形进度条,水平进度条,包括完整回调类的书写,主要理解透View的坐标系,这个很重要,我觉得这些不理解透,这中间的算法虽说简单但是写不出来

1圆形进度条(其实就是画圆弧了)

首先应该画最外层的圆(为了避免背景是白的或黑色的很难看,也就是在圆形基础上画圆弧)代码如下

center = getWidth() / 2;
radius = center - mCircleWidth / 2;//从圆弧中点画弧
paint.setAntiAlias(true);
paint.setColor(firstColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(mCircleWidth);
//draw cicle
canvas.drawCircle(center, center, radius, paint);
用于定义的圆弧的形状和大小的界限
RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
paint.setColor(seconedColor);
//draw progress
//oval :指定圆弧的外轮廓矩形区域。
//startAngle: 圆弧起始角度,单位为度。
// sweepAngle: 圆弧扫过的角度,顺时针方向,单位为度。
//useCenter: 如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形。
// paint: 绘制圆弧的画板属性,如颜色,是否填充等。
canvas.drawArc(oval, -90, mProgress, false, paint); //根据进度画圆弧
更新到进度,我用的是Handler,不断的Post自己已达到进度的更改

private Runnable progressRunnable = new Runnable() {
    @Override
    public void run() {
        thumbMove += 1;
        unitMoveLength += 1;
        mProgress++;
        if (mProgress == 360) {
            mProgress = 0;
        }
        if (unitMoveLength >= width) {
            unitMoveLength = width;
        } else if (unitMoveLength <= 0) {
            unitMoveLength = 0;
        }
        if(thumbMove >= range){
            thumbMove = range;
        }else if(thumbMove <= 0){
            thumbMove = 0;
        }
        weakRefHandler.postDelayed(this, speed);
        weakRefHandler.sendMessage(weakRefHandler.obtainMessage());
    }
};
2 绘制水平进度条

//绘制水平进度条
private void drawRoundHorizentalProgress(Canvas canvas) {
    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(firstColor);
    paint.setDither(true);
    //draw bg
    paint.setStrokeWidth(mCircleWidth);
    RectF rectBg = new RectF(0, 0, width, height);
    canvas.drawRoundRect(rectBg, coradius, coradius, paint);
    //draw progress
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(seconedColor);
    RectF progressRectF = new RectF(0, 0, unitMoveLength, height);
    canvas.drawRoundRect(progressRectF, coradius, coradius, paint);
}

3 看下最终的效果好了,以上就是这些了,主要还是多练,这些都是规则的图形,只是调用API就可以实现的,让我们共同努力吧,超高级,大神之路迈进!

Tips:


一、translate canvas左上角定位

示例:canvas.translate(10,10);

二、clip canvas裁剪

Region.Op.DIFFERENCE 表示“挖去”画布中的一块区域;

Region.Op.REPLACE 表示“替换”画布区域;

Region.Op.UNION 表示“合并”画布区域;

Region.Op.XOR 表示“合并”后“挖去”重叠的画布区域;

Region.Op.REVERSE_DIFFERENCE 表示“反向挖去”画布区域,即在新的画布区域中“挖去”当前画布区域;

Region.Op.INTERSECT 表示“交集”,即在新的画布和当前画布的共同区域。

示例:canvas.clipRect(40, 40,100, 100, Region.Op.INTERSECT)。

三、画布和图层Layer

画布(bitmap)、图层(Layer)和Bitmap它们之间的关系如下:
图层(Layer):每一次调用canvas.drawXXX系列函数时,都会生成一个透明图层来专门来画这个图形,比如我们在画矩形时的透明图层就是这个概念。
画布(bitmap):每一个画布都是一个bitmap,所有的图像都是画在bitmap上的!我们知道每一次调用canvas.drawxxx函数时,都会生成一个专用的透明图层来画这个图形,画完以后,就盖在了画布上。所以如果我们连续调用五个draw函数,那么就会生成五个透明图层,画完之后依次盖在画布上显示。
画布有两种,第一种是view的原始画布,是通过onDraw(Canvas canvas)函数传进来的,其中参数中的canvas就对应的是view的原始画布,控件的背景就是画在这个画布上的!
另一种是人造画布,通过saveLayer()、new Canvas(bitmap)这些方法来人为新建一个画布。尤其是saveLayer(),一旦调用saveLayer()新建一个画布以后,以后的所有draw函数所画的图像都是画在这个画布上的,只有当调用restore()、resoreToCount()函数以后,才会返回到原始画布上绘制。
Canvas:这个概念比较难理解,我们可以把Canvas理解成画板,Bitmap理解成透明画纸,而Layer则理解成图层;每一个draw函数都对应一个图层,在一个图形画完以后,就放在画纸上显示。而一张张透明的画纸则一层层地叠加在画板上显示出来。我们知道画板和画纸都是用夹子夹在一起的,所以当我们旋转画板时,所有画纸都会跟着旋转!当我们把整个画板裁小时,所以的画纸也都会变小了!
这一点非常重要,当我们利用saveLayer来生成多个画纸时,然后最上层的画纸调用canvas.rotate(30)是把画板给旋转了,所有的画纸也都被旋转30度!这一点非常注意
另外,如果最上层的画纸调用canvas.clipRect()将画板裁剪了,那么所有的画纸也都会被裁剪。唯一能够恢复的操作是调用canvas.revert()把上一次的动作给取消掉!
但在利用canvas绘图与画板不一样的是,画布的影响只体现在以后的操作上,以前画上去的图像已经显示在屏幕上是不会受到影响的。
这一点一定要理解出来,大家最好实践下。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值