Canvas 方法效果演示

好记性不如烂笔头,记录一下canvas常见的方法及效果演示

Canvas多使用在自定义View中,onDraw()方法绘制图形

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

canvas 可以大致分为一下几类:

  1. drawXXX 等一系列绘制方法
  2. scale rotate clip 等对画布进行操作
  3. save restore 回滚相关方法

drawText()/drawBitmap()

String text = "MillerJK";
Paint mBluePaint = new Paint();
mBluePaint.setColor(Color.BLUE);
mBluePaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 40, getResources().getDisplayMetrics()));// **setTextSize() and setStrokeWidth() need px here**
canvas.drawText(text, 200, 200, mBluePaint);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.aa);
canvas.drawBitmap(bitmap, 200, 200, mBluePaint);

Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
canvas.drawPoint(200, 200, paint);

效果图:

这里写图片描述

(妹子好漂亮!)

从图中可见文字在坐标(200,200)的右上角,而图片则是在右下角,如果想让TEXT文本 图片 以(200,200)为中心 ,可参考如下代码

   Rect rect = new Rect();
   mBluePaint.getTextBounds(text, 0, text.length(), rect); 
   canvas.drawText(text, 300 - rect.width() / 2, 300 + rect.height() / 2, mBluePaint);
   canvas.drawBitmap(bitmap, 200 - bitmap.getWidth() / 2, 200 - bitmap.getHeight() / 2, mBluePaint);

将文字的信息记录在Rect中,通过该类提供的api我们可以通过width() , height(),left,top 等,android 里还有RectF类,Rect传递参数为int类型,而RecF传递参数为float类型,相对来说保存的信息更加精确。

drawRect()/drawArc()/drawOval()/drawLine()

  Paint paint = new Paint();
  paint.setStyle(Paint.Style.STROKE);
  paint.setColor(Color.RED);
  canvas.drawRect(new RectF(400, 100, 600, 200), mPaint);
  canvas.drawArc(new RectF(650, 100, 750, 200), 0, 90, false, mPaint);//true 弧线和圆心组成的区域  false只显示弧线 圆心则是矩形的中心
  Rect rect = new Rect(100, 100, 300, 250);
  canvas.drawOval(new RectF(rect), mPaint);  //绘制内切圆
  canvas.drawLine(100, 300, 300, 300, mPaint);//绘制直线

效果图:

这里写图片描述

SweepGradient

  SweepGradient mSweepGradient = new SweepGradient(240, 360, new int[]{Color.WHITE, Color.BLACK}, new float[]{0.5f, 1f});
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setShader(mSweepGradient);
        canvas.drawCircle(240, 360, 200, mPaint);

效果如下:

这里写图片描述

其中colors至少两种 , postions 可以为null,需要注意一旦postions不为null,需保证colors和postions 数组length()必须相同,否则会报错:

java.lang.IllegalArgumentException: color and position arrays must be of equal length

从这个例子也可以很容易看出,扫描是从右边开始向下顺时针扫的,White 所占的区域为0-0.5 黑色所占的区域为0.5-1 。

Path

lineTo()

        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);

        mPath.lineTo(100, 100);
        mPath.lineTo(100, 200);
        mPath.lineTo(150, 250);
        canvas.drawPath(mPath, paint);

效果图如下:
这里写图片描述

默认情况下Path的起始点是屏幕的左上角(0,0),如果不想起始点为(0,0)的话就使用moveTo(x,y)方法,如果想让终止点和起始点封闭需使用close()方法, 比如以上代码,在lineTo(100,100)之前添加 mPath.moveTo(50,50),在lineTo(150,250)之后添加 mPath.close() ,则效果如下:

这里写图片描述

addArc() arcTo()

        Path path = new Path();
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);

        RectF rectF = new RectF(200, 200, 400, 400);
        path.moveTo(50, 50);
        path.arcTo(rectF, 0, 90);
        path.addArc(new RectF(rectF), -90, -150);
        canvas.drawPath(path, paint);

效果如下:

这里写图片描述

addArc可以直接加入一段椭圆弧。使用arcTo还需要使用moveTo指定当前点的坐标。arcTo如果当前点坐标和曲线的起始点不是同一个点的话,还会自动添加一条直线补齐路径。

quadTo()

        mPath.moveTo(20, 50);
        mPath.lineTo(100, 100);
        mPath.quadTo(100, 200, 150, 250); //二阶贝塞尔曲线   三阶贝塞尔曲线:cubicTo()
        canvas.drawPath(mPath, mPaint);

效果如下:

这里写图片描述

二阶贝塞尔 三阶贝塞尔 曲线 此处不在说些什么。参考:

http://blog.csdn.net/wuqilianga/article/details/51494282

translate()

        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(20);

        canvas.translate(200, 200);
        canvas.drawPoint(0,0,paint);

        paint.setColor(Color.BLUE);
        canvas.translate(100,100);
        canvas.drawPoint(0,0,paint);

效果如下:

这里写图片描述

Note

画布先以(200,200)为原点,然后执行translate(100,100) ,在200 的基础上有向右下各移动 100,如不理解可参考:http://blog.csdn.net/harvic880925/article/details/39080931

rotate()

        Paint paint = new Paint();
        paint.setColor(Color.RED);

        Rect rect = new Rect(300,10,500,100);
        canvas.drawRect(rect,paint);

        paint.setColor(Color.BLUE);
        canvas.rotate(30);
        canvas.drawRect(rect,paint);

        paint.setColor(Color.DKGRAY);
        Rect rect1 = new Rect(550,10,700,100);
        canvas.drawRect(rect1,paint);

效果图如下:

这里写图片描述

这个例子几乎是参照 http://blog.csdn.net/harvic880925/article/details/39080931 写的,参照这篇博客的rotate方法,这里我有多画了一个矩形,主要是为了说明两点:

1、每次调用canvas.drawXXXX系列函数来绘图进,都会产生一个全新的Canvas画布。
2、如果在DrawXXX前,调用平移、旋转等函数来对Canvas进行了操作,那么这个操作是不可逆的!每次产生的画布的最新位置都是这些操作后的位置。(关于Save()、Restore()的画布可逆问题的后面再讲)

scale()

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);

        canvas.drawRect(new Rect(10, 10, 400, 400), paint);

        paint.setColor(Color.BLUE);
        canvas.scale(0.5f, 0.5f,205,205);
        canvas.drawRect(new Rect(10, 10, 400, 400), paint);

效果图:

这里写图片描述

scale 包括两种方法,区别在于设置缩放中心。

scale(sx, sy, px, py) 的源码如下:

  public final void scale(float sx, float sy, float px, float py) {
        translate(px, py);
        scale(sx, sy);
        translate(-px, -py);
    }

最开始看到这段源码的时候,有些疑惑。总感觉上述代码实现的效果应该如下:

wrong

这里写图片描述

但是源码就是源码是不会错误的啊!那应该怎么理解?

其实上面在rotate() 我验证那两点总结,你只要是在认真的看一看,然后结合这个scale()源码想一想,自然就会明白了。

关于Canvas 就先写到这 ,至于 restore save 找时间在写一篇总结!这两个方法作用也是想当的大。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值