精华内容
下载资源
问答
  • AndroidCanvas android canvas学习
  • Android Canvas

    万次阅读 2012-02-15 14:41:49
    Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么...他们提供了图形处理相关的: Canvas、ColorFilter、Point(点)和
     
    

    Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳过这篇文章。

    大部分2D使用的api都在android.graphics和android.graphics.drawable包中。他们提供了图形处理相关的: Canvas、ColorFilter、Point(点)和RetcF(矩形)等,还有一些动画相关的:AnimationDrawable、BitmapDrawable和TransitionDrawable等。以图形处理来说,我们最常用到的就是在一个View上画一些图片、形状或者自定义的文本内容,这里我们都是使用Canvas来实现的。你可以获取View中的Canvas对象,绘制一些自定义形状,然后调用View. invalidate方法让View重新刷新,然后绘制一个新的形状,这样达到2D动画效果。下面我们就主要来了解下Canvas的使用方法。

    Canvas对象的获取方式有两种:一种我们通过重写View.onDraw方法,View中的Canvas对象会被当做参数传递过来,我们操作这个Canvas,效果会直接反应在View中。另一种就是当你想创建一个Canvas对象时使用的方法:

    1
    2
    Bitmap b = Bitmap.createBitmap( 100 , 100 , Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);

    上面代码创建了一个尺寸是100*100的Bitmap,使用它作为Canvas操作的对象,这时候的Canvas就是使用创建的方式。当你使用创建的Canvas在bitmap上执行绘制方法后,你还可以将绘制的结果提交给另外一个Canvas,这样就可以达到两个Canvas协作完成的效果,简化逻辑。但是android SDK建议使用View.onDraw参数里提供的Canvas就好,没必要自己创建一个新的Canvas对象。接下来我们看看Canvas提供我们哪些绘制图形的方法。我们创建一个自定义View对象,使用onDraw方法提供的Canvas进行绘制图形。

    CanvasDemoActivity.java:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    package com.android777.demo.uicontroller.graphics;
     
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.os.Bundle;
    import android.view.View;
     
    public class CanvasDemoActivity extends Activity {
     
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super .onCreate(savedInstanceState);
     
             setContentView( new CustomView1( this ));
     
         }
     
         /**
          * 使用内部类 自定义一个简单的View
          * @author Administrator
          *
          */
         class CustomView1 extends View{
     
             Paint paint;
     
             public CustomView1(Context context) {
                 super (context);
                 paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
                 paint.setColor(Color.YELLOW);
                 paint.setStrokeJoin(Paint.Join.ROUND);
                 paint.setStrokeCap(Paint.Cap.ROUND);
                 paint.setStrokeWidth( 3 );
             }
     
             //在这里我们将测试canvas提供的绘制图形方法
             @Override
             protected void onDraw(Canvas canvas) {
     
             }
     
         }
     
    }

     

     

    执行结果是一片黑色的区域,因为在自定义的CustomView1中,我们没有做任何的绘制操作。canvas提供的绘制图形的方法都是以draw开头的,我们可以查看api:

    从上面方法的名字看来我们可以知道Canvas可以绘制的对象有:弧线(arcs)、填充颜色(argb和color)、Bitmap、圆(circle和oval)、点(point)、线(line)、矩形(Rect)、图片(Picture)、圆角矩形(RoundRect)、文本(text)、顶点(Vertices)、路径(path)。通过组合这些对象我们可以画出一些简单有趣的界面出来,但是光有这些功能还是不够的,如果我要画一个仪表盘(数字围绕显示在一个圆圈中)呢? 幸好Android还提供了一些对Canvas位置转换的方法:rorate、scale、translate、skew(扭曲)等,而且它允许你通过获得它的转换矩阵对象(getMatrix方法,不知道什么是转换矩阵?看这里)直接操作它。这些操作就像是虽然你的笔还是原来的地方画,但是画纸旋转或者移动了,所以你画的东西的方位就产生变化。为了方便一些转换操作,Canvas还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置。下面我们就演示下canvas的一些简单用法:

    1
    2
    3
    4
    protected void onDraw(Canvas canvas) {
     
         canvas.drawCircle( 100 , 100 , 90 , paint);
    }

    效果是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Override
    protected void onDraw(Canvas canvas) {
     
         //绘制弧线区域
     
         RectF rect = new RectF( 0 , 0 , 100 , 100 );
     
         canvas.drawArc(rect, //弧线所使用的矩形区域大小
                 0 //开始角度
                 90 , //扫过的角度
                 false , //是否使用中心
                 paint);
     
    }


    使用下面的代码:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    protected void onDraw(Canvas canvas) {
     
         //绘制弧线区域
     
         RectF rect = new RectF( 0 , 0 , 100 , 100 );
     
         canvas.drawArc(rect, //弧线所使用的矩形区域大小
                 0 //开始角度
                 90 , //扫过的角度
                 true , //是否使用中心
                 paint);
     
    }

     

    两图对比我们可以发现,当drawArcs(rect,startAngel,sweepAngel,useCenter,paint)中的useCenter为false时,弧线区域是用弧线开始角度和结束角度直接连接起来的,当useCenter为true时,是弧线开始角度和结束角度都与中心点连接,形成一个扇形。

     

    1
    2
    3
    4
    5
    protected void onDraw(Canvas canvas) {
     
         canvas.drawColor(Color.BLUE);
     
    }

     

    canvas.drawColor是直接将View显示区域用某个颜色填充满。

     

    1
    2
    3
    4
    5
    6
    7
    @Override
    protected void onDraw(Canvas canvas) {
     
         //画一条线
         canvas.drawLine( 10 , 10 , 100 , 100 , paint);
     
    }

     

    Canvas.drawOval:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Override
    protected void onDraw(Canvas canvas) {
     
         //定义一个矩形区域
         RectF oval = new RectF( 0 , 0 , 200 , 300 );
         //矩形区域内切椭圆
         canvas.drawOval(oval, paint);
     
    }

     

    canvas.drawPosText:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Override
    protected void onDraw(Canvas canvas) {
     
         //按照既定点 绘制文本内容
         canvas.drawPosText( "Android777" , new float []{
                 10 , 10 , //第一个字母在坐标10,10
                 20 , 20 , //第二个字母在坐标20,20
                 30 , 30 , //....
                 40 , 40 ,
                 50 , 50 ,
                 60 , 60 ,
                 70 , 70 ,
                 80 , 80 ,
                 90 , 90 ,
                 100 , 100
         }, paint);
     
    }

     

    canvas.drawRect:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
         @Override
         protected void onDraw(Canvas canvas) {
     
             RectF rect = new RectF( 50 , 50 , 200 , 200 );
     
             canvas.drawRect(rect, paint);
     
         }
     
    }

     

    canvas.drawRoundRect:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override
    protected void onDraw(Canvas canvas) {
     
         RectF rect = new RectF( 50 , 50 , 200 , 200 );
     
         canvas.drawRoundRect(rect,
                             30 , //x轴的半径
                             30 , //y轴的半径
                             paint);
     
    }

     

    canvas.drawPath:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Override
    protected void onDraw(Canvas canvas) {
     
         Path path = new Path(); //定义一条路径
         path.moveTo( 10 , 10 ); //移动到 坐标10,10
         path.lineTo( 50 , 60 );
         path.lineTo( 200 , 80 );
         path.lineTo( 10 , 10 );
     
         canvas.drawPath(path, paint);
     
    }

    canvas.drawTextOnPath:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
             @Override
             protected void onDraw(Canvas canvas) {
     
                 Path path = new Path(); //定义一条路径
                 path.moveTo( 10 , 10 ); //移动到 坐标10,10
                 path.lineTo( 50 , 60 );
                 path.lineTo( 200 , 80 );
                 path.lineTo( 10 , 10 );
     
    //          canvas.drawPath(path, paint);
                 canvas.drawTextOnPath( "Android777开发者博客" , path, 10 , 10 , paint);
     
             }

     

    位置转换方法,canvas.rorate和canvas.translate:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    @Override
    protected void onDraw(Canvas canvas) {
     
         paint.setAntiAlias( true );
         paint.setStyle(Style.STROKE);
         canvas.translate(canvas.getWidth()/ 2 , 200 ); //将位置移动画纸的坐标点:150,150
         canvas.drawCircle( 0 , 0 , 100 , paint); //画圆圈
     
         //使用path绘制路径文字
         canvas.save();
         canvas.translate(- 75 , - 75 );
         Path path = new Path();
         path.addArc( new RectF( 0 , 0 , 150 , 150 ), - 180 , 180 );
         Paint citePaint = new Paint(paint);
         citePaint.setTextSize( 14 );
         citePaint.setStrokeWidth( 1 );
         canvas.drawTextOnPath( "http://www.android777.com" , path, 28 , 0 , citePaint);
         canvas.restore();
     
         Paint tmpPaint = new Paint(paint); //小刻度画笔对象
         tmpPaint.setStrokeWidth( 1 );
     
         float  y= 100 ;
         int count = 60 ; //总刻度数
     
         for ( int i= 0 ; i <count ; i++){
             if (i% 5 == 0 ){
                 canvas.drawLine(0f, y, 0 , y+12f, paint);
                 canvas.drawText(String.valueOf(i/ 5 + 1 ), -4f, y+25f, tmpPaint);
     
             } else {
                 canvas.drawLine(0f, y, 0f, y +5f, tmpPaint);
             }
             canvas.rotate( 360 /count,0f,0f); //旋转画纸
         }
     
         //绘制指针
         tmpPaint.setColor(Color.GRAY);
         tmpPaint.setStrokeWidth( 4 );
         canvas.drawCircle( 0 , 0 , 7 , tmpPaint);
         tmpPaint.setStyle(Style.FILL);
         tmpPaint.setColor(Color.YELLOW);
         canvas.drawCircle( 0 , 0 , 5 , tmpPaint);
         canvas.drawLine( 0 , 10 , 0 , - 65 , paint);
     
    }


     

    上面几个例子基本已经将常用的canvas.draw*方法测试过了,我们结合一些事件,做一些有用户交互的应用:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    package com.android777.demo.uicontroller.graphics;
     
    import java.util.ArrayList;
     
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PointF;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
     
    public class CanvasDemoActivity extends Activity {
     
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super .onCreate(savedInstanceState);
     
             setContentView( new CustomView1( this ));
     
         }
     
         /**
          * 使用内部类 自定义一个简单的View
          * @author Administrator
          *
          */
         class CustomView1 extends View{
     
             Paint paint;
             private ArrayList<PointF> graphics = new ArrayList<PointF>();
             PointF point;
     
             public CustomView1(Context context) {
                 super (context);
                 paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
                 paint.setColor(Color.YELLOW);
                 paint.setStrokeJoin(Paint.Join.ROUND);
                 paint.setStrokeCap(Paint.Cap.ROUND);
                 paint.setStrokeWidth( 3 );
     
             }
     
             @Override
             public boolean onTouchEvent(MotionEvent event) {
     
                 graphics.add( new PointF(event.getX(),event.getY()));
     
                 invalidate(); //重新绘制区域
     
                 return true ;
             }
     
             //在这里我们将测试canvas提供的绘制图形方法
             @Override
             protected void onDraw(Canvas canvas) {
                 for (PointF point : graphics) {
                     canvas.drawPoint(point.x, point.y, paint);
                 }
    //          super.onDraw(canvas);
     
             }
         }
     
    }

    当用户点击时将出现一个小点,拖动时将画出一条用细点组成的虚线:

     

     


    展开全文
  • Android Canvas绘图描述Android Canvas 方法总结

    万次阅读 多人点赞 2018-04-23 00:17:47
    Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么...他们提供了图形处理相关的: Canvas、ColorFilter、Point(点)和...

    Canvas绘制描述

    Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳过这篇文章。

    大部分2D使用的api都在android.graphics和android.graphics.drawable包中。他们提供了图形处理相关的: Canvas、ColorFilter、Point(点)和RetcF(矩形)等,还有一些动画相关的:AnimationDrawable、 BitmapDrawable和TransitionDrawable等。以图形处理来说,我们最常用到的就是在一个View上画一些图片、形状或者自定义的文本内容,这里我们都是使用Canvas来实现的。你可以获取View中的Canvas对象,绘制一些自定义形状,然后调用View. invalidate方法让View重新刷新,然后绘制一个新的形状,这样达到2D动画效果。下面我们就主要来了解下Canvas的使用方法。

    Canvas对象的获取方式有两种:一种我们通过重写View.onDraw方法,View中的Canvas对象会被当做参数传递过来,我们操作这个Canvas,效果会直接反应在View中。另一种就是当你想创建一个Canvas对象时使用的方法:

     

    Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);

    上面代码创建了一个尺寸是100*100的Bitmap,使用它作为Canvas操作的对象,这时候的Canvas就是使用创建的方式。当你使用创建的Canvas在bitmap上执行绘制方法后,你还可以将绘制的结果提交给另外一个Canvas,这样就可以达到两个Canvas协作完成的效果,简化逻辑。但是android SDK建议使用View.onDraw参数里提供的Canvas就好,没必要自己创建一个新的Canvas对象。接下来我们看看Canvas提供我们哪些绘制图形的方法。我们创建一个自定义View对象,使用onDraw方法提供的Canvas进行绘制图形。

    CanvasDemoActivity.java:

    package com.android777.demo.uicontroller.graphics;
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.os.Bundle;
    import android.view.View;
    
    public class CanvasDemoActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(new CustomView1(this));
        }
        /**
        * 使用内部类 自定义一个简单的View
        * @author Administrator
        *
        */
        class CustomView1 extends View{
            Paint paint;
    
            public CustomView1(Context context) {
                super(context);
                paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
                paint.setColor(Color.YELLOW);
                paint.setStrokeJoin(Paint.Join.ROUND);
                paint.setStrokeCap(Paint.Cap.ROUND);
                paint.setStrokeWidth(3);
            }
    
            //在这里我们将测试canvas提供的绘制图形方法
            @Override
            protected void onDraw(Canvas canvas) {
    
            }
        }
    }

    执行结果是一片黑色的区域,因为在自定义的CustomView1中,我们没有做任何的绘制操作。canvas提供的绘制图形的方法都是以draw开头的,我们可以查看api:

    Css_bugtester

    从上面方法的名字看来我们可以知道Canvas可以绘制的对象有:弧线(arcs)、填充颜色(argb和color)、 Bitmap、圆(circle和oval)、点(point)、线(line)、矩形(Rect)、图片(Picture)、圆角矩形 (RoundRect)、文本(text)、顶点(Vertices)、路径(path)。通过组合这些对象我们可以画出一些简单有趣的界面出来,但是光有这些功能还是不够的,如果我要画一个仪表盘(数字围绕显示在一个圆圈中)呢? 幸好Android还提供了一些对Canvas位置转换的方法:rorate、scale、translate、skew(扭曲)等,而且它允许你通过获得它的转换矩阵对象(getMatrix方法,不知道什么是转换矩阵?看这里) 直接操作它。这些操作就像是虽然你的笔还是原来的地方画,但是画纸旋转或者移动了,所以你画的东西的方位就产生变化。为了方便一些转换操作,Canvas 还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置。下面我们就演示下canvas的一些简单用法:

     

    protected void onDraw(Canvas canvas) {
        canvas.drawCircle(100, 100, 90, paint);
    }
    

    效果是:

    @Override
    protected void onDraw(Canvas canvas) {
        //绘制弧线区域
        RectF rect = new RectF(0, 0, 100, 100);
        canvas.drawArc(rect, //弧线所使用的矩形区域大小
        0, //开始角度
        90, //扫过的角度
        false, //是否使用中心
        paint);
    }



     

    使用下面的代码:

    protected void onDraw(Canvas canvas) {
        //绘制弧线区域
        RectF rect = new RectF(0, 0, 100, 100);
        canvas.drawArc(rect, //弧线所使用的矩形区域大小
        0, //开始角度
        90, //扫过的角度
        true, //是否使用中心
        paint);
    }

    两图对比我们可以发现,当 drawArcs(rect,startAngel,sweepAngel,useCenter,paint)中的useCenter为false时,弧线区域是用弧线开始角度和结束角度直接连接起来的,当useCenter为true时,是弧线开始角度和结束角度都与中心点连接,形成一个扇形。

     

    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.BLUE);
    }
    

    canvas.drawColor是直接将View显示区域用某个颜色填充满。

    @Override
    protected void onDraw(Canvas canvas) {
        //画一条线
        canvas.drawLine(10, 10, 100, 100, paint);
    }

     

    Canvas.drawOval:

    @Override
    protected void onDraw(Canvas canvas) {
        //定义一个矩形区域
        RectF oval = new RectF(0,0,200,300);
        //矩形区域内切椭圆
        canvas.drawOval(oval, paint);
    }

     

    canvas.drawPosText:

    @Override
    protected void onDraw(Canvas canvas) {
        //按照既定点 绘制文本内容
        canvas.drawPosText("Android777", new float[]{
        10,10, //第一个字母在坐标10,10
        20,20, //第二个字母在坐标20,20
        30,30, //....
        40,40,
        50,50,
        60,60,
        70,70,
        80,80,
        90,90,
        100,100
        }, paint);
    }

     

     

    canvas.drawRect:

    @Override
    protected void onDraw(Canvas canvas) {
        RectF rect = new RectF(50, 50, 200, 200);
        canvas.drawRect(rect, paint);
    }

     

    canvas.drawRoundRect:

    @Override
    protected void onDraw(Canvas canvas) {
        RectF rect = new RectF(50, 50, 200, 200);
        canvas.drawRoundRect(rect,
        30, //x轴的半径
        30, //y轴的半径
        paint);
    }
    

     

     

    canvas.drawPath:

    @Override
    protected void onDraw(Canvas canvas) {
        Path path = new Path(); //定义一条路径
        path.moveTo(10, 10); //移动到 坐标10,10
        path.lineTo(50, 60);
        path.lineTo(200,80);
        path.lineTo(10, 10);
        canvas.drawPath(path, paint);
    }

     

    canvas.drawTextOnPath:

    @Override
    protected void onDraw(Canvas canvas) {
        Path path = new Path(); //定义一条路径
        path.moveTo(10, 10); //移动到 坐标10,10
        path.lineTo(50, 60);
        path.lineTo(200,80);
        path.lineTo(10, 10);
        // canvas.drawPath(path, paint);
        canvas.drawTextOnPath("Android777开发者博客", path, 10, 10, paint);
    }

     

     

     

    位置转换方法,canvas.rorate和canvas.translate:

    @Override
    protected void onDraw(Canvas canvas) {
        paint.setAntiAlias(true);
        paint.setStyle(Style.STROKE);
        canvas.translate(canvas.getWidth()/2, 200); //将位置移动画纸的坐标点:150,150
        canvas.drawCircle(0, 0, 100, paint); //画圆圈
        //使用path绘制路径文字
        canvas.save();
        canvas.translate(-75, -75);
        Path path = new Path();
        path.addArc(new RectF(0,0,150,150), -180, 180);
        Paint citePaint = new Paint(paint);
        citePaint.setTextSize(14);
        citePaint.setStrokeWidth(1);
        canvas.drawTextOnPath("http://www.android777.com", path, 28, 0, citePaint);
        canvas.restore();
        Paint tmpPaint = new Paint(paint); //小刻度画笔对象
        tmpPaint.setStrokeWidth(1);
        float y=100;
        int count = 60; //总刻度数
        for(int i=0 ; i <count ; i++){
            if(i%5 == 0){
                canvas.drawLine(0f, y, 0, y+12f, paint);
                canvas.drawText(String.valueOf(i/5+1), -4f, y+25f, tmpPaint);
            }else{
                canvas.drawLine(0f, y, 0f, y +5f, tmpPaint);
            }
            canvas.rotate(360/count,0f,0f); //旋转画纸
        }
        //绘制指针
        tmpPaint.setColor(Color.GRAY);
        tmpPaint.setStrokeWidth(4);
        canvas.drawCircle(0, 0, 7, tmpPaint);
        tmpPaint.setStyle(Style.FILL);
        tmpPaint.setColor(Color.YELLOW);
        canvas.drawCircle(0, 0, 5, tmpPaint);
        canvas.drawLine(0, 10, 0, -65, paint);
    }

     

     

    上面几个例子基本已经将常用的canvas.draw*方法测试过了,我们结合一些事件,做一些有用户交互的应用:

    package com.android777.demo.uicontroller.graphics;
    import java.util.ArrayList;
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PointF;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    public class CanvasDemoActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new CustomView1(this));
    }
    /**
    * 使用内部类 自定义一个简单的View
    * @author Administrator
    *
    */
    class CustomView1 extends View{
        Paint paint;
        private ArrayList<PointF> graphics = new ArrayList<PointF>();
        PointF point;
    
        public CustomView1(Context context) {
            super(context);
            paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
            paint.setColor(Color.YELLOW);
            paint.setStrokeJoin(Paint.Join.ROUND);
            paint.setStrokeCap(Paint.Cap.ROUND);
            paint.setStrokeWidth(3);
        }
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            graphics.add(new PointF(event.getX(),event.getY()));
            invalidate(); //重新绘制区域
            return true;
        }
        //在这里我们将测试canvas提供的绘制图形方法
        @Override
        protected void onDraw(Canvas canvas) {
            for (PointF point : graphics) {
                canvas.drawPoint(point.x, point.y, paint);
            }
            // super.onDraw(canvas);
        }
    }
    }

     

    当用户点击时将出现一个小点,拖动时将画出一条用细点组成的虚线:

     

    canvas的应用

     

    canva还可以制作很多自定义控件,比如google日历的monthview就是用canvas绘制出来的,github上有很多使用canva的项目,所有的图表库都是用canvas绘制的。

     

     

     

     

     

    Android Canvas 方法总结

     

    简介

    在自定义 View的时候,我们经常需要绘制一些自己想要的效果。这里就需要使用Canvas对象。下面将Canvas对象常用方法做个笔记,方便记忆。


    对Canvas进行操作

    对Canvas的一系列操作,是指对Canvas进行旋转、平移、缩放等操作。这些操作可以让Canvas对象使用起来更加便捷。

    Canvas平移

    
    /** 
     * 画布向(100,50)方向平移 
     *  
     * 参数1: 向X轴方向移动100距离 
     * 参数2: 向Y轴方向移动50距离   
     */
     canvas.translate(100, 50);
    

    Canvas缩放

    
    /** 
     * 在X轴方向放大为原来2倍,Y轴方向方大为原来的4倍 
     * 参数1: X轴的放大倍数 
     * 参数2: Y轴的放大倍数 
     */
    canvas.scale(2, 4);
    
    /** 
     * 在X轴方向放大为原来2倍,Y轴方向方大为原来的4倍 
     * 参数1: X轴的放大倍数 
     * 参数2: Y轴的放大倍数 
     * 参数3: 原点X坐标
     * 参数4: 原点Y坐标
     */
    canvas.scale(2, 4,100,100);
    1. Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    2. Canvas c = new Canvas

    Canvas缩放图示

    Canvas旋转

    
    /** 
     * 原点为中心,旋转30度(顺时针方向为正方向 )
     * 参数: 旋转角度 
     */
    canvas.rotate(30);
    
    /** 
     * 以(100,100)为中心,旋转30度,顺时针方向为正方向 
     * 参数: 旋转角度 
     */
    canvas.rotate(30,100,100);
    

     

    Canvas旋转图示

    Canvas操作例子

    
     Paint p = new Paint();
     p.setColor(Color.argb(50,255,100,100));
     canvas.drawRect(0,0,200,200,p); // 以原始Canvas画出一个矩形1
     canvas.translate(300,300); // 将Canvas平移  (100,100)
     p.setColor(Color.argb(50,100,255,100));
     canvas.drawRect(0,0,200,200,p); //  矩形2
     canvas.rotate(30); //将Canvas旋转30
     p.setColor(Color.argb(50,100,0,255));
     canvas.drawRect(0,0,200,200,p); // 矩形3
     canvas.scale(2, 2); // 将Canvas以原点为中心,放大两倍
     p.setColor(Color.argb(50,255,255,0));
     canvas.drawRect(0,0,200,200,p); // 矩形4
    

     

    Canvas示例

    Canvas保存和还原

    Canvas提供了几个方法,让我们可以方便的对Canvas的状态进行更改和还原。
    这些方法是:save()restore()restoreToCount(int saveCount)

    我们在对Canvas进行平移、旋转、放大等操作时候,可以调用save()方法,将当前修改过的Canvas状态进行保存,调用restore() 方法后,会将Canvas还原成最近的一个save() 的状态。

    save()方法还会有一个返回值,我们也可以调用restoreToCount(int saveCount)方法,将这个返回值作为参数传递进去,就可以将Canvas还原成某一个特定的save()状态。

    
     canvas.translate(100,100); // 平移(100,100)
     int save1 = canvas.save(); // 保存Canvas状态(状态1)
     canvas.scale(2, 2); // 放大2倍
     int save2 = canvas.save(); // 保存Canvas状态(状态2)
     canvas.restore(); // 返回最新的save状态,即状态2
     canvas.restoreToCount(save1);// 手动指定的返回到 状态1
    

    画文字

    
    /** 
     * 参数2:文本的x轴的开始位置 
     * 参数2:文本Y轴的结束位置 
     * 参数3:画笔对象 
     */  
    canvas.drawText("开始写字了!",50, 50, p);// 画文本  
    
    /** 
     * 参数2:要从第几个字开始绘制 
     * 参数3:要绘制到第几个文字 
     * 参数4:文本的x轴的开始位置 
     * 参数5:文本Y轴的结束位置 
     * 参数6:画笔对象 
     */  
    canvas.drawText("开始写字了!",2,5, 50, 50, p);// 画文本,结果为:“写字了”  
    /** 
     * 参数2:路径 
     * 参数3:距离路径开始位置的偏移量 
     * 参数4:距离路径上下的偏移量(可以为负数) 
     * 参数5:画笔对象 
     */  
    canvas.drawTextOnPath("1234567890101123123", path, 0, -50, p);  
    

    画圆

    
    /**
     * 参数1:圆心X 
     * 参数2:圆心Y 
     * 参数3:半径R 
     * 参数4:画笔对象 
     */           
    canvas.drawCircle(200, 200, 100, p);  
    

    画线

    
    /* 
     * 参数1:startX 
     * 参数2:startY 
     * 参数3:stopX 
     * 参数4:stopY 
     * 参数5:画笔对象 
     */   
    canvas.drawLine(100, 100, 300, 300, p);// 画线  
    /* 
     * 同时绘制多条线。 
     * 参数1:float数组:每四个一组为一条线。最后不足四个,就忽略那些值。 
     * 参数2:画笔对象 
     */  
    canvas.drawLines(new float[]{100,100,200,200,200,100,300,100}, p);  
    

    画椭圆

    /* 
     *  参数1:float left 
     *  参数2:float top 
     *  参数3:float right 
     *  参数4:float bottom 
     */  
    RectF oval = new RectF(150, 200, 500, 400);// 画一个椭圆  
    canvas.drawOval(oval, p);  
    

    画弧度

    
    /**
     *  画圆弧
     *  参数1:RectF对象。 
     *  参数2:开始的角度。(水平向右为0度顺时针反向为正方向) 
     *  参数3:扫过的角度 
     *  参数4:是否和中心连线 
     *  参数5:画笔对象 
     */  
    canvas.drawArc(oval, 20, 180, false, p);  
    

    矩形

    
    /** 
     *  矩形 
     *  参数1:float left 
     *  参数2:float top 
     *  参数3:float right 
     *  参数4:float bottom 
     */  
    canvas.drawRect(100,100, 200, 200, p);  
        
    //画圆角矩形    
    RectF oval3 = new RectF(80, 260, 200, 300);// 设置个新的长方形    
    canvas.drawRoundRect(oval3, 20, 5, p);//第二个参数是x半径,第三个参数是y半径    
    

    多边形

    
    /**  
     * Path类封装复合(多轮廓几何图形的路径  
     * 由直线段*、二次曲线,和三次方曲线,也可画以油画。drawPath(路径、油漆),要么已填充的或抚摸  
     * (基于油漆的风格),或者可以用于剪断或画画的文本在路径。  
     */   
    Path path = new Path();  // 路径对象  
    path.moveTo(80, 200);// 此点为多边形的起点    
    path.lineTo(120, 250);    
    path.lineTo(80, 250);    
    //....  可以添加多个点。构成多边形  
    path.close(); // 使终点和起点链接,构成封闭图形   
            canvas.drawPath(path, p);    
    

    画贝塞尔曲线

    
    p.setStyle(Style.STROKE);  
    Path path2=new Path();    
    path2.moveTo(100, 100);//设置Path的起点   
    /** 
     * 参数1、2:x1,y1为控制点的坐标值 
     * 参数3、4:x2,y2为终点的坐标值 
     */  
    path2.quadTo(300, 100, 400, 400); //设置贝塞尔曲线的控制点坐标和终点坐标    
    path2.quadTo(500, 700, 800, 800);  
    canvas.drawPath(path2, p);//画出贝塞尔曲线    
    

    画点

    
    /** 
     * 参数1、2:点的x、y坐标 
     */  
    canvas.drawPoint(60, 390, p);//画一个点    
    /** 
     * 参数1:多个点,每两个值为一个点。最后个数不够两个的值,忽略。 
     */  
    canvas.drawPoints(new float[]{60,400,65,400,70,400}, p);//画多个点    
    

    画图片

    
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);   
    /** 
     * 参数1:bitmap对象 
     * 参数2:图像左边坐标点 
     * 参数3:图像上边坐标点 
     */  
    canvas.drawBitmap(bitmap, 200,300, p);  

     

     

    Paint类

     

    要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布上,这样才可以显示在手机屏幕上。Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设置,主要方法如下: 

       setAntiAlias: 设置画笔的锯齿效果。 
       setColor: 设置画笔颜色 
       setARGB:  设置画笔的a,r,p,g值。 
       setAlpha:  设置Alpha值 
       setTextSize: 设置字体尺寸。 
       setStyle:  设置画笔风格,空心或者实心。 
       setStrokeWidth: 设置空心的边框宽度。 
       getColor:  得到画笔的颜色 
       getAlpha:  得到画笔的Alpha值。 

           下面是一个简单的示例 来说明这些方法的使用。先来看看运行效果吧。 

     

       package eoe.Demo;
      
       import android.content.Context;
       import android.graphics.Canvas;
       import android.graphics.Color;
       import android.graphics.Paint;
       import android.util.Log;
       import android.view.KeyEvent;
       import android.view.MotionEvent;
       import android.view.View;
      
       public class GameView extends View implements Runnable {
      
       public final static String TAG = "Example_05_03_GameView";
       // 声明Paint对象
       private Paint mPaint = null;
      
       public GameView(Context context) {
           super(context);
           // 构建对象
           mPaint = new Paint();
      
           // 开启线程
           new Thread(this).start();
       }
      
       @Override
       protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
      
       // 设置Paint为无锯齿
       mPaint.setAntiAlias(true);
      
       // 设置Paint的颜色
       mPaint.setColor(Color.RED);
       mPaint.setColor(Color.BLUE);
       mPaint.setColor(Color.YELLOW);
       mPaint.setColor(Color.GREEN);
       // 同样是设置颜色
       mPaint.setColor(Color.rgb(255, 0, 0));
      
       // 提取颜色
       Color.red(0xcccccc);
       Color.green(0xcccccc);
      
       // 设置paint的颜色和Alpha值(a,r,g,b)
       mPaint.setAlpha(220);
      
       // 这里可以设置为另外一个paint对象
       // mPaint.set(new Paint());
       // 设置字体的尺寸
       mPaint.setTextSize(14);
      
       // 设置paint的风格为“空心”
       // 当然也可以设置为"实心"(Paint.Style.FILL)
       mPaint.setStyle(Paint.Style.STROKE);
      
       // 设置“空心”的外框的宽度
       mPaint.setStrokeWidth(5);
      
       // 得到Paint的一些属性 颜色、Alpha值、外框的宽度、字体尺寸
       Log.i("TAG", "paint Color------>" + mPaint.getColor());
       Log.i(TAG, "paint Alpha------->" + mPaint.getAlpha());
       Log.i("TAG", "paint StrokeWidth--------->" + mPaint.getStrokeWidth());
       Log.i("TAG", "paint TextSize----------->" + mPaint.getTextSize());
      
       // 绘制一空心个矩形
       canvas.drawRect((320 - 80), 20, (320 - 80) / 2 + 80, 20 + 40, mPaint);
      
       // 设置风格为实心
       mPaint.setStyle(Paint.Style.FILL);
      
       mPaint.setColor(Color.GREEN);
     
       // 绘制绿色实心矩形
       canvas.drawRect(0, 20, 40, 20 + 40, mPaint);
       }
      
      // 触笔事件
      public boolean onTouchEvent(MotionEvent event) {
          return true;
      }
      
      // 按键按下事件
      public boolean onKeyDown(int keyCode, KeyEvent event) {
          return true;
      }
      
      // 按键弹起事件
      public boolean onKeyUp(int keyCode, KeyEvent event) {
          return true;
      }
      
      public boolean onKeyMultiple(int KeyCode, int repeatCount, KeyEvent event) {
          return true;
      }
      
      @Override
      public void run() {
          while (!Thread.currentThread().isInterrupted()) {
          try {
              Thread.sleep(100);
          } catch (Exception e) {
              Thread.currentThread().interrupt();
          }
         // 更新界面
         postInvalidate();
         }
     }
     }
     
     
     package eoe.Demo;
     
     import android.app.Activity;
     import android.os.Bundle;
     
     public class Activity01 extends Activity {
         /** Called when the activity is first created. */
         private GameView mGameView;
     
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
     
             setContentView(R.layout.main);
     
             mGameView = new GameView(this);
     
             setContentView(mGameView);
     }
     } 

        /**  
         * Paint类介绍  
         *   
         * Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色,  
         * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法,  
         * 大体上可以分为两类,一类与图形绘制相关,一类与文本绘制相关。         
         *   
         * 1.图形绘制  
         * setARGB(int a,int r,int g,int b);  
         * 设置绘制的颜色,a代表透明度,r,g,b代表颜色值。  
         *   
         * setAlpha(int a);  
         * 设置绘制图形的透明度。  
         *   
         * setColor(int color);  
         * 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。  
         *   
         * setAntiAlias(boolean aa);  
         * 设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。  
         *   
         * setDither(boolean dither);  
         * 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰  
         *   
         * setFilterBitmap(boolean filter);  
         * 如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示  
         * 速度,本设置项依赖于dither和xfermode的设置  
         *   
         * setMaskFilter(MaskFilter maskfilter);  
         * 设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等       *   
         * setColorFilter(ColorFilter colorfilter);  
         * 设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果  
         *   
         * setPathEffect(PathEffect effect);  
         * 设置绘制路径的效果,如点画线等  
         *   
         * setShader(Shader shader);  
         * 设置图像效果,使用Shader可以绘制出各种渐变效果  
         *  
         * setShadowLayer(float radius ,float dx,float dy,int color);  
         * 在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色  
         *   
         * setStyle(Paint.Style style);  
         * 设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE  
         *   
         * setStrokeCap(Paint.Cap cap);  
         * 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式  
         * Cap.ROUND,或方形样式Cap.SQUARE  
         *   
         * setSrokeJoin(Paint.Join join);  
         * 设置绘制时各图形的结合方式,如平滑效果等  
         *   
         * setStrokeWidth(float width);  
         * 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度  
         *   
         * setXfermode(Xfermode xfermode);  
         * 设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果  
         *   
         * 2.文本绘制  
         * setFakeBoldText(boolean fakeBoldText);  
         * 模拟实现粗体文字,设置在小字体上效果会非常差  
         *   
         * setSubpixelText(boolean subpixelText);  
         * 设置该项为true,将有助于文本在LCD屏幕上的显示效果  
         *   
         * setTextAlign(Paint.Align align);  
         * 设置绘制文字的对齐方向  
         *   
         * setTextScaleX(float scaleX);  
         * 设置绘制文字x轴的缩放比例,可以实现文字的拉伸的效果  
         *   
         * setTextSize(float textSize);  
         * 设置绘制文字的字号大小  
         *   
         * setTextSkewX(float skewX);  
         * 设置斜体文字,skewX为倾斜弧度  
         *   
         * setTypeface(Typeface typeface);  
         * 设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等  
         *   
         * setUnderlineText(boolean underlineText);  
         * 设置带有下划线的文字效果  
         *   
         * setStrikeThruText(boolean strikeThruText);  
         * 设置带有删除线的效果  
         *   
         */ 

     

    在Android中需要通过graphics类来显示2D图形。

      graphics中包括了Canvas(画布)、Paint(画笔)、Color(颜色)、Bitmap(图像)等常用的类。graphics具有绘制点、线、颜色、2D几何图形、图像处理等功能。

    1.Color(颜色)类

      Android系统中颜色的常用表示方法有以下3种:

      (1)int color = Color.BLUE;
      (2)int color = Color.argb(150,200,0,100);
      (3)在xml文件中定义颜色;

      在实际应用当中,我们常用的颜色有以下一些,其颜色常量及其表示的颜色如下所示:

      Color.BLACK        黑色                               Color.GREEN                 绿色
      Color.BLUE         蓝色                               Color.LTGRAY                浅灰色
      Color.CYAN         青绿色                             Color.MAGENTA               红紫色
      Color.DKGRAY       灰黑色                             Color.RED                   红色
      Color.YELLOW       黄色                               Color.TRANSPARENT           透明
      Color.GRAY         灰色                               Color.WHITE                 白色

     

    2.Paint(画笔)类

       要绘制图形,首先得调整画笔,按照自己的开发需要设置画笔的相关属性。Pain类的常用属性设置方法如下:

      setAntiAlias();            //设置画笔的锯齿效果
      setColor();                //设置画笔的颜色
      setARGB();                 //设置画笔的A、R、G、B值
      setAlpha();                //设置画笔的Alpha值
      setTextSize();             //设置字体的尺寸
      setStyle();                //设置画笔的风格(空心或实心)
      setStrokeWidth();          //设置空心边框的宽度
      getColor();                //获取画笔的颜色

     

    3.Canvas(画布)类

      画笔属性设置好之后,还需要将图像绘制到画布上。Canvas类可以用来实现各种图形的绘制工作,如绘制直线、矩形、圆等等。Canvas绘制常用图形的方法如下:

      绘制直线:canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint);
      绘制矩形:canvas.drawRect(float left, float top, float right, float bottom, Paint paint);
      绘制圆形:canvas.drawCircle(float cx, float cy, float radius, Paint paint);
      绘制字符:canvas.drawText(String text, float x, float y, Paint paint);
      绘制图形:canvas.drawBirmap(Bitmap bitmap, float left, float top, Paint paint);

     

    4.自定义View的基本实现方法

      首先,我们需要自定义一个类,比如MyView,继承于View类。然后,复写View类的onDraw()函数。最后,在onDraw()函数中使用Paint和Canvas对象绘制我们需要的图形。

     

    5.动手实践

      在这里,我使用上面提到的一些方法,绘制了一幅简单的北京奥运宣传画,包括奥运五环,“北京欢迎您”的宣传标语以及福娃。做成后的效果图如图1所示。 

    图1 Android_OlympicLogo效果图

      其中,使用了自定义的MyView类,在MyView类中,重写了onDraw()函数,并定义几种不同的画笔,分别用来绘制各种颜色的奥运五环以及绘制字符串“北京欢迎您”等。具体的MyView.java源代码如下。

     

      package com.example.android_olympiclogo;
      
      import android.view.View;
      import android.content.Context;
      import android.graphics.BitmapFactory;
      import android.graphics.Canvas;
      import android.graphics.Color;
      import android.graphics.Paint;
      import android.graphics.Paint.Style;
     
      public class MyView extends View {
     
         public MyView(Context context) {
             super(context);
         }
         
         public void onDraw(Canvas canvas) {
             
             Paint paint_blue = new Paint();                        //绘制蓝色的环
             paint_blue.setColor(Color.BLUE);
             paint_blue.setStyle(Style.STROKE);
             paint_blue.setStrokeWidth(10);        
             canvas.drawCircle(110,150,60,paint_blue);
             
             Paint paint_yellow = new Paint();                //绘制黄色的环
             paint_yellow.setColor(Color.YELLOW);
             paint_yellow.setStyle(Style.STROKE);
             paint_yellow.setStrokeWidth(10);
             canvas.drawCircle((float)175.5, 210, 60, paint_yellow);
             
             Paint paint_black = new Paint();                   //绘制黑色的环
             paint_black.setColor(Color.BLACK);
             paint_black.setStyle(Style.STROKE);
             paint_black.setStrokeWidth(10);
             canvas.drawCircle(245, 150, 60, paint_black);
             
             Paint paint_green = new Paint();                  //绘制绿色的环
             paint_green.setColor(Color.GREEN);
             paint_green.setStyle(Style.STROKE);
             paint_green.setStrokeWidth(10);
             canvas.drawCircle(311, 210, 60, paint_green);
             
             Paint paint_red = new Paint();                       //绘制红色的环
             paint_red.setColor(Color.RED);
             paint_red.setStyle(Style.STROKE);
             paint_red.setStrokeWidth(10);
             canvas.drawCircle(380, 150, 60, paint_red);
             
             Paint paint_string = new Paint();                   //绘制字符串
             paint_string.setColor(Color.BLUE);
             paint_string.setTextSize(20);
             canvas.drawText("Welcome to Beijing", 245, 310, paint_string);
             
             Paint paint_line = new Paint();                       //绘制直线
             paint_line.setColor(Color.BLUE);
             canvas.drawLine(240, 310, 425, 310, paint_line);
             
             Paint paint_text = new Paint();                      //绘制字符串
             paint_text.setColor(Color.BLUE);
             paint_text.setTextSize(20);
             canvas.drawText("北京欢迎您", 275, 330, paint_text);
             
             //绘制福娃图片
             canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.fuwa), 35, 340, paint_line);
         }
     }

     

     

     

     

      此外,还需要将自定义的MyView视图显示到手机屏幕上,所以需要在MainAcitivity.java中加载MyView视图,可以使用setContentView()方法,具体的MainAcitivity.java源代码如下。

     package com.example.android_olympiclogo;
     
     import android.os.Bundle;
     import android.app.Activity;
     import android.view.Menu;
     import android.view.MenuItem;
     import android.support.v4.app.NavUtils;
     
     public class MainActivity extends Activity {
     
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             //setContentView(R.layout.activity_main);
             setContentView(new MyView(this));                              //加载MyView
         }
     
         @Override
         public boolean onCreateOptionsMenu(Menu menu) {
             getMenuInflater().inflate(R.menu.activity_main, menu);
             return true;
         }
         
     }

     

     

    当然了,还需要将福娃的图片放在res下的drawable-hdpi目录下。这样才可以使用BitmapFactory.decodeResource(getResources(),R.drawable.fuwa)方法加载该图片。

     

    展开全文
  • Android Canvas绘图Demo

    2015-06-23 00:07:41
    Android Canvas绘图演示代码
  • Android Canvas 简单打地鼠游戏,Android Canvas 简单打地鼠游戏。
  • android-canvas-examples 我的 Android Canvas 示例 来源 三角形: :
  • 主要为大家详细介绍了android canvas使用line画半园,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Android canvas 放大 缩小 平移 各种绘图 自定义view 请自行修改
  • 主要介绍了 Android canvas drawBitmap方法详解及实例的相关资料,需要的朋友可以参考下
  • 主要介绍了Android canvas画图操作之切割画布实现方法,通过clipRect方法实现canvas画布的切割操作,需要的朋友可以参考下
  • android canvas 绘图笔记

    万次阅读 2016-03-11 10:21:07
    android canvas 绘图笔记1.PathEffect类画虚线 Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setStyle(Paint.Style.STROKE); p.setColor(Color.WHITE); p.setStrokeWidth(1); PathEffect

    android canvas 绘图笔记

    1.PathEffect类

    画虚线

     Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
            p.setStyle(Paint.Style.STROKE);
            p.setColor(Color.WHITE);
            p.setStrokeWidth(1);
            PathEffect effect = new DashPathEffect(new float[]{getDip2px(4), getDip2px(4), getDip2px(4), getDip2px(4)}, 1);
            p.setPathEffect(effect);
            p.setAlpha(125);//透明度50%
            p.setColor(getResources().getColor(R.color.line_chart_dash_line));
            canvas.drawLine(0, ScreenHeight / 2, ScreenWidth, ScreenHeight / 2, p);
            canvas.drawLine(ScreenWidth / 2, 0, ScreenWidth / 2, getBottom() - getDip2px(25), p);

    2.android onMeasure

    3.android BlurMaskFilter

    ***Android MaskFilter的基本使用:***
    
    MaskFilter类可以为Paint分配边缘效果。
            对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter:
    
            BlurMaskFilter   指定了一个模糊的样式和半径来处理Paint的边缘。
            EmbossMaskFilter  指定了光源的方向和环境光强度来添加浮雕效果。
    
            要应用一个MaskFilter,可以使用setMaskFilter方法,并传递给它一个MaskFilter对象。下面的例子是对一个已经存在的Paint应用一个EmbossMaskFilter:
    

    Android MaskFilter的基本使用:

    MaskFilter类可以为Paint分配边缘效果。
        对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter:
    
        BlurMaskFilter   指定了一个模糊的样式和半径来处理Paint的边缘。
        EmbossMaskFilter  指定了光源的方向和环境光强度来添加浮雕效果。
    
        要应用一个MaskFilter,可以使用setMaskFilter方法,并传递给它一个MaskFilter对象。下面的例子是对一个已经存在的Paint应用一个EmbossMaskFilter:
    

    关于设置硬件加速不能用的方法

    LAYER_TYPE_NONE

    LAYER_TYPE_SOFTWARE

    LAYER_TYPE_HARDWARE

    View级别
    
    您可以在运行时用以下的代码关闭单个view的硬件加速:
    
    myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    注:您不能在view级别开启硬件加速
    为什么需要这么多级别的控制?
    很明显,硬件加速能够带来性能提升,android为什么要弄出这么多级别的控制,
    而不是默认就是全部硬件加速呢?原因是并非所有的2D绘图操作支持硬件加速,
    如果您的程序中使用了自定义视图或者绘图调用,程序可能会工作不正常。
    如果您的程序中只是用了标准的视图和Drawable,放心大胆的开启硬件加速吧!
    具体是哪些绘图操作不支持硬件加速呢?以下是已知不支持硬件加速的绘图操作:
    
    Canvas
    clipPath()
    clipRegion()
    drawPicture()
    drawPosText()
    drawTextOnPath()
    drawVertices()
    Paint
    setLinearText()
    setMaskFilter()
    setRasterizer()
    
    另外还有一些绘图操作,开启和不开启硬件加速,效果不一样:
    
    Canvas
    clipRect(): XOR, Difference和ReverseDifference裁剪模式被忽略,3D变换将不会应用在裁剪的矩形上。
    
    drawBitmapMesh():colors数组被忽略
    
    drawLines():反锯齿不支持
    
    setDrawFilter():可以设置,但无效果
    
    Paint
    
    setDither(): 忽略
    setFilterBitmap():过滤永远开启
    setShadowLayer():只能用在文本上
    ComposeShader
    ComposeShader
    只能包含不同类型的shader (比如一个BitmapShader和一个LinearGradient,但不能是两个BitmapShader实例)
    
    ComposeShader不能包含ComposeShader
    
    如果应用程序受到这些影响,您可以在受影响的部分调用setLayerType(View.LAYER_TYPE_SOFTWARE, null),这样在其它地方仍然可以享受硬件加速带来的好处
    

    2.Paint(画笔)类

       要绘制图形,首先得调整画笔,按照自己的开发需要设置画笔的相关属性。Pain类的常用属性设置方法如下:
    
      setAntiAlias();            //设置画笔的锯齿效果
    
      setColor();                 //设置画笔的颜色
    
      setARGB();                 //设置画笔的A、R、G、B值
    
      setAlpha();                 //设置画笔的Alpha值
    
      setTextSize();             //设置字体的尺寸
    
      setStyle();                  //设置画笔的风格(空心或实心)
    
      setStrokeWidth();        //设置空心边框的宽度
    
      getColor();                  //获取画笔的颜色
    

      

     3.Canvas(画布)类

      画笔属性设置好之后,还需要将图像绘制到画布上。Canvas类可以用来实现各种图形的绘制工作,如绘制直线、矩形、圆等等。Canvas绘制常用图形的方法如下:
    
      绘制直线:canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint);
    
      绘制矩形:canvas.drawRect(float left, float top, float right, float bottom, Paint paint);
    
      绘制圆形:canvas.drawCircle(float cx, float cy, float radius, Paint paint);
    
      绘制字符:canvas.drawText(String text, float x, float y, Paint paint);
    
      绘制图形:canvas.drawBirmap(Bitmap bitmap, float left, float top, Paint paint);
    

    Shader 渐变色设置

     //设置渐变器后绘制
            //为Paint设置渐变器
            Shader mShasder = new LinearGradient(0, 0, 40, 60, new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
            mPaint.setShader(mShasder);
            //设置阴影
            mPaint.setShadowLayer(45, 10, 10, Color.GRAY);

    Paint.Style区别

    Paint.Style.FILL    :填充内部
    Paint.Style.FILL_AND_STROKE  :填充内部和描边
    Paint.Style.STROKE  :仅描边
    

    Region 判断是否在路径范围内

    “onTouchEvent 在自定义View 中”

    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        switch (event.getAction()) {  
        case MotionEvent.ACTION_DOWN:  
            // 按下  
            cx = (int) event.getX();  
            cy = (int) event.getY();  
            // 通知重绘  
            postInvalidate();   //该方法会调用onDraw方法,重新绘图  
            break;  
        case MotionEvent.ACTION_MOVE:  
            // 移动  
            cx = (int) event.getX();  
            cy = (int) event.getY();  
            // 通知重绘  
            postInvalidate();  
            break;  
        case MotionEvent.ACTION_UP:  
            // 抬起  
            cx = (int) event.getX();  
            cy = (int) event.getY();  
            // 通知重绘  
            postInvalidate();  
            break;  
        }  
    
        /* 
         * 备注1:此处一定要将return super.onTouchEvent(event)修改为return true,原因是: 
         * 1)父类的onTouchEvent(event)方法可能没有做任何处理,但是返回了false。 
         * 2)一旦返回false,在该方法中再也不会收到MotionEvent.ACTION_MOVE及MotionEvent.ACTION_UP事件。 
         */  
        //return super.onTouchEvent(event);  
        return true;    
    }  
    

    RectF

    • Android Rect和RectF的区别*

      1、精度不一样,Rect是使用int类型作为数值,RectF是使用float类型作为数值
      2、两个类型提供的方法也不是完全一致
      
      Rect:
      equals(Object obj)   (for some reason it as it's own implementation of equals)
      exactCenterX()
      exactCenterY()
      flattenToString()
      toShortString()
      unflattenFromString(String str)
      
      RectF:
      round(Rect dst)
      roundOut(Rect dst)
      set(Rect src)
      

    Shader

    //设置渐变器后绘制
            //为Paint设置渐变器
            Shader mShasder = new LinearGradient(0, 0, 40, 60, new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
            mPaint.setShader(mShasder);
            //设置阴影
            mPaint.setShadowLayer(45, 10, 10, Color.GRAY);
    Paint p=new Paint();
    LinearGradient lg=new LinearGradien(0,0,100,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR);  
    参数一为渐变起初点坐标x位置,
    参数二为y轴位置,
    参数三和四分辨对应渐变终点,
    最后参数为平铺方式,这里设置为镜像
    Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变,代码如下: mPaint.setShader(lg);
    
    canvas.drawCicle(0,0,200,mPaint); //参数3为画圆的半径,类型为float型。
    
    
    它除了定义开始颜色和结束颜色以外还可以定义,多种颜色组成的分段渐变效果
    
    LinearGradient shader = new LinearGradient(0, 0, endX, endY, new int[]{startColor, midleColor, endColor},new float[]{0 , 0.5f, 1.0f}, TileMode.MIRROR);
    
    其中参数new int[]{startColor, midleColor, endColor}是参与渐变效果的颜色集合,
    
    其中参数new float[]{0 , 0.5f, 1.0f}是定义每个颜色处于的渐变相对位置,
    
    这个参数可以为null,如果为null表示所有的颜色按顺序均匀的分布
    

    LinearGradient有两个构造函数;

    public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile)

    参数:
    float x0: 渐变起始点x坐标
    
    float y0:渐变起始点y坐标
    
    float x1:渐变结束点x坐标
    
    float y1:渐变结束点y坐标
    
    int[] colors:颜色 的int 数组
    
    float[] positions: 相对位置的颜色数组,可为null,  若为null,可为null,颜色沿渐变线均匀分布
    
    Shader.TileMode tile: 渲染器平铺模式
    
    public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,Shader.TileMode tile)
    float x0: 渐变起始点x坐标
    
    float y0:渐变起始点y坐标
    
    float x1:渐变结束点x坐标
    
    float y1:渐变结束点y坐标
    
    int color0: 起始渐变色
    
    int color1: 结束渐变色
    
    Shader.TileMode tile: 渲染器平铺模式
    
    
    Android 透明度渐变
    

    android 代码截屏

     /**
         * Returns the bitmap that represents the chart.
         *
         * @return
         */
        public Bitmap getChartBitmap() {
            // Define a bitmap with the same size as the view
            Bitmap returnedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
            // Bind a canvas to it
            Canvas canvas = new Canvas(returnedBitmap);
            // Get the view's background
            Drawable bgDrawable = getBackground();
            if (bgDrawable != null)
                // has background drawable, then draw it on the canvas
                bgDrawable.draw(canvas);
            else
                // does not have background drawable, then draw white background on
                // the canvas
                canvas.drawColor(Color.WHITE);
            // draw the view on the canvas
            draw(canvas);
            // return the bitmap
            return returnedBitmap;
        }
     /**
         * Returns the bitmap that represents the chart.
         *
         * @return
         */
        public Bitmap getChartBitmap() {
            // Define a bitmap with the same size as the view
            Bitmap returnedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
            // Bind a canvas to it
            Canvas canvas = new Canvas(returnedBitmap);
            // Get the view's background
            Drawable bgDrawable = getBackground();
            if (bgDrawable != null)
                // has background drawable, then draw it on the canvas
                bgDrawable.draw(canvas);
            else
                // does not have background drawable, then draw white background on
                // the canvas
                canvas.drawColor(Color.WHITE);
            // draw the view on the canvas
            draw(canvas);
            // return the bitmap
            return returnedBitmap;
        }

    对canvas的translate()方法的理解

    canvas.save();//锁画布(为了保存之前的画布状态)
            canvas.translate(10, 10);//把当前画布的原点移到(10,10),后面的操作都以(10,10)作为参照点,默认原点为(0,0)
            drawScene(canvas);
            canvas.restore();//把当前画布返回(调整)到上一个save()状态之前
    
            canvas.save();//锁画布(为了保存之前的画布状态)
            canvas.translate(160, 10);//把当前画布的原点移到(160,10),后面的操作都以(160,10)作为参照点,
            canvas.clipRect(10, 10, 90, 90);//这里的真实坐标为左上(170,170)、右下(250,250)
            canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
            drawScene(canvas);
            canvas.restore();

    图片镜像

    public Bitmap convertBmp(Bitmap bmp) {  
            int w = bmp.getWidth();  
            int h = bmp.getHeight();  
    
            Matrix matrix = new Matrix();  
            matrix.postScale(-1, 1); // 镜像水平翻转  
            Bitmap convertBmp = Bitmap.createBitmap(bmp, 0, 0, w, h, matrix, true);  
    
            return convertBmp;  
        }  
    展开全文
  • android canvas 3D旋转木马 图片立体展示
  • android canvas与图层的关系

    千次阅读 2016-05-09 19:34:38
    android canvas与图层的关系

    在自定义view中可以通过canvas在屏幕上绘制一些文字,图片,图形之类的效果,canvas这个类给我们提供了很多绘制的方法,比如绘制一段文字在屏幕上:

    package com.example.customview;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * Created by admin on 2016/5/9.
     */
    public class CustomView extends View {
        private Paint mPaint = null;
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
        }
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setTextSize(35);//设置文字大小
            canvas.drawText("canvas绘制文字",100,100,mPaint);
        }
    }
    这是在父view的100,100坐标哪里绘制文字的,canvas绘制的方法一般都是前缀draw....比入drawBitmap()绘制图片,Canvas类如下方法:



    canvas方法多用几篇就知道了,今天主要是讲canvas与图层的关系,先讲下canvas几个方法

    1:translate(floatdx, floatdy)

    package com.example.view;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * Created by Adminis on 2016/5/9.
     */
    public class CustomView extends View {
        private Paint mPaint;
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
        }
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Rect rect = new Rect(0,0,400,400);
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(5);
            canvas.drawRect(rect,mPaint);
        }
    }
    

    效果如下:


    现在通过canvas的translate(100,100)向右平移100px,向下平移100px,效果:


    从效果来看就知道translate(dx,dy)这二个参数的意思

    dx:是向右移动dx距离

    dy:是向下移动dy距离

    canvas还有其他类似view的动画方法

    scale(dx,dy)缩放

    rotate(dx,dy)旋转

    这是一些canvas实现对画布的操作,但是有没有想过这个矩形是怎么画上去的,也许会说这不是废话么,通过canvas画上去的,所以就得出结论就是画布就是屏幕显示区域,现在把上面绘制的矩形改为空心的

    package com.example.view;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * Created by Adminis on 2016/5/9.
     */
    public class CustomView extends View {
        private Paint mPaint;
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
        }
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Rect rect = new Rect(0,0,400,400);
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(5);
            mPaint.setStyle(Paint.Style.STROKE);
            canvas.drawRect(rect, mPaint);
            canvas.translate(100,100);
            mPaint.setColor(Color.GREEN);
            canvas.drawRect(rect, mPaint);
        }
    }
    图:


    发现平移后的矩形和平移前的矩形没有重合,这是为什么呢?这是因为屏幕显示和canvas不是一个等同的概念,屏幕相当于一个显示我们所看到效果的一个容器,你可以随便往屏幕上显示任何可在坐标点范围内可见的,而canvas可以看作是一个透明的图层,我们每次调用canvas的draw...方法都会产生一个透明的层,既然知道了canvas每次draw都会产生一个透明的图层,这样也就好解释上面的问题,在没有平移前,它的坐标点为(0,0) 平移了(100,100)相当于(100,100)是第二个图层的原点,这样二个图层就有重叠的部分,而canvas对象是系统通过onDraw()方法提供给我们的显示到屏幕上,关于屏幕于canvas图层我在别的博客找到了一个很好的图演示图层合成到屏幕上



    而图层是无限大的,而屏幕大小是有限的,比如在使用canvas把一段位子绘制到图层上的坐标是负数,而在屏幕上显示不出来就是就是因为屏幕是从(0,0)到(屏幕的宽度,屏幕的高度)这个范围是可见的,超过这二个点的范围是不可见的,既然在图层上画出来也显示看不见的,从上面的分析中可得出2个结论

    1:每次调用canvas对象的draw...方法都会产生一个透明的图层

    2:canvas与屏幕合成过程中,如果超出屏幕范围是不可见的,


    canvas还有2个非常重要的方法 一般使用了canvas的什么平移,缩放等操作必用到的2个方法就是save()和restore()

    你可以在屏幕上绘制多个图层,我们知道activity有activity任务栈,你也可以想象的把图层集合想象成一个栈,栈是一个先进后出的数据结构,你可以把图层看作是一个activity任务栈,一层一层的往屏幕上叠起来,现在写个例子:

    package com.example.view;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * Created by Adminis on 2016/5/9.
     */
    public class CustomView extends View {
        private Paint mPaint;
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
        }
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //绘制一个图层背景  没有在图层上画什么东西 一个空的图层
            canvas.drawColor(Color.parseColor("#e5e5e5"));
            //保存当前画布大小即整屏 (这是保存上一个画布的操作)
            canvas.save();
            //绘制一个矩形
            canvas.clipRect(new Rect(100, 100, 800, 800));
            canvas.drawColor(Color.GREEN);
            //恢复整屏画布 也就是回复到(00)坐标点
            canvas.restore();
            canvas.drawColor(Color.);
        }
    }
    
    这三个图层可以一个个画出来看出它的合成到屏幕的过程,结果是这样的,

      

    第二个图层:第二个图层的宽度800-100,高度为800-100就是图中显示的区域大小


    第三层:


    最终是显示整屏的红色,因为最后一层是(0,0)开始会把前2层图层覆盖了,如果canvas不调用restore()回复的方法 效果是这样的:


    你会发现它刚好在第二个图层的上面,我们可以在第三个图层画一个矩形,但是宽和高比第二个图层的矩形小点,这样就可以看出来它在第二个层上面,

    package com.example.view;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * Created by Adminis on 2016/5/9.
     */
    public class CustomView extends View {
        private Paint mPaint;
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
        }
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //绘制一个图层背景  没有在图层上画什么东西 一个空的图层
            canvas.drawColor(Color.parseColor("#e5e5e5"));
            //保存当前画布大小即整屏 (这是保存上一个画布的操作)
            canvas.save();
            //绘制一个矩形
            canvas.clipRect(new Rect(100, 100, 800, 800));
            canvas.drawColor(Color.GREEN);
    //        //恢复整屏画布 也就是回复到(00)坐标点
    //        canvas.restore();
            canvas.clipRect(new Rect(100, 100,700, 700));
            canvas.drawColor(Color.RED);
        }
    }
    
    效果:


    从效果上可以得出一个结论,如果canvas没有调用restore()方法的话,canvas画图层是从它上一个图层栈中以上一个图层原点为原点开始绘制并合并到屏幕上,现在写一个例子多次调用save()和restore()方法会有什么奇怪的效果出来:

    package com.example.view;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * Created by Adminis on 2016/5/9.
     */
    public class CustomView extends View {
        private Paint mPaint;
        public CustomView(Context context) {
            super(context);
        }
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
        }
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.parseColor("#e5e5e5"));
            //保存的画布大小为全屏幕大小
            canvas.save();
            //这个矩形会在上一个画布上进行draw 也就是(00)位置
            canvas.clipRect(new Rect(100, 100, 600, 600));
            //这个画布在前一个矩形大小为500,500的位置
            canvas.drawColor(Color.GREEN);
            //保存画布大小为Rect(100, 100, 600, 600)
            canvas.save();
            //这个会在上一个矩形为500500的位置上
            canvas.clipRect(new Rect(200, 200, 700, 700));
            canvas.drawColor(Color.BLUE);
            //保存画布大小为Rect(200, 200, 700, 700)
            canvas.save();
            //这个会在原点为(200,200)大小为500的我、canvas        canvas.clipRect(new Rect(300, 300, 600, 600));
            canvas.drawColor(Color.BLACK);
            //保存画布大小为Rect(300, 300, 600, 600)
            canvas.save();
            //这个会在原点为(300,300)为原点大小为300的位置上进行canvas
            canvas.clipRect(new Rect(400, 400, 500, 500));
            canvas.drawColor(Color.YELLOW);
        }
    }
    
    这个注释写的很仔细了,最终的效果图:


    这是调用了四次save()方法但是没调用restore()方法,可以模拟activity栈画一个类似activity任务栈的图:


    现在可以先调用一次restore()方法看效果:为了看出效果我把最后一层的大小和上一层大小一样


    你会发现把上一层黑色的给盖住了,如果连续三次调用restore()方法,和刚才一样思考就是到了绿色的那个区域(canvas)效果是和你想象的一样,集合图层栈所描述的那样每次调用一次日store()方法都会把这个图层拉出栈顶,然后把下一个图层当作当前要使用的画布

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#e5e5e5"));
        //保存的画布大小为全屏幕大小
        canvas.save();
        canvas.clipRect(new Rect(100, 100, 600, 600));
        canvas.drawColor(Color.GREEN);
        canvas.save();
        canvas.clipRect(new Rect(200, 200, 500, 500));
        canvas.drawColor(Color.BLUE);
        canvas.save();
        canvas.clipRect(new Rect(300, 300, 400, 400));
        canvas.drawColor(Color.BLACK);
    }
    效果如下:


    我现在调用一次restore()效果是这样的:


    因为调用了一次restore()方法,就会把蓝色的图层当作新的画布,而调用3次restore()方法效果是这样的


    总结下这二个方法的使用

    Save():每次调用Save()函数,都会把当前的画布的状态进行保存,然后放入特定的栈中;
    restore():每当调用Restore()函数,就会把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布,并在这个画布上做画

    终于写完了 洗澡睡觉





    展开全文
  • Android Canvas基础详解

    万次阅读 多人点赞 2018-05-28 20:16:17
    Android通过Canvas类暴露了很多drawXXX方法,我们可以通过这些方法绘制各种各样的图形。Canvas绘图有三个基本要素:Canvas、绘图坐标系以及Paint。Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas...
  • Android Canvas绘图

    千次阅读 2018-10-31 17:52:36
    以图形处理来说,我们最常用到的就是在一个View上画一些图片、形状或者自定义的文本内容,这里我们都是使用Canvas来实现的。你可以获取View中的Canvas对象,绘制一些自定义形状,然后调用View. invalidate方法让View...
  • Android Canvas rotate 和translate 两个方法的研究
  • android canvas常用的方法解析(一)

    千次阅读 2016-05-18 19:07:36
    android canvas常用的方法解析
  • android canvas.drawText在矩形内文字居中

    千次阅读 2018-05-28 23:11:04
    android canvas.drawText在矩形内文字居中 https://blog.csdn.net/hursing/article/details/18703599
  • Android Canvas中rotate()和translate()两个方法详解
  • android canvas layer (图层)详解

    千次阅读 2016-11-21 17:30:08
    android canvas layer (图层)详解与进阶 1 概述 前面的canvas变换文章中,已经粗略的讲解过saveLayer的知识,只是图层的概念没有详细的讲解。这里将详细讲解layer。在使用相关方法和flag的时候,先关闭...
  • 本文介绍如何通过Android Canvas的路径,把几何图形转化为程序进行动态绘制。 首先,对图片进行分析,可以看出图形是由8块一样的扇形拼接而成,每一块图扇形是由一条垂直于y轴的直线,一个45度夹角的
  • Android canvas画圆

    千次阅读 2018-11-30 09:53:27
    android:id="@+id/ballView2" android:layout_width=“match_parent” android:layout_height=“wrap_content” /&gt; BallView页面 package com.lll.day03; import android.content.Contex...
  • android canvas详解

    千次阅读 2014-04-24 09:42:47
    摘要 Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳过这篇文章。 大部分2D使用的api都在android.graphics...
  • android canvas画图 切割画布(clipRect)

    千次阅读 2011-04-12 20:16:00
    android canvas画图 切割画布(clipRect)
  • android Canvas 裁剪

    千次阅读 2013-12-31 14:41:25
    首先想到是canvas 的 slip方法,其提供了很多样式的裁剪,这里就不一一指出。 要弄清的是,这里canvas裁剪,是对bitmap的裁剪吗,我的回答 :NO 。 个人理解:canvas只是画布,其slip方法就像创建一个裁剪选区,...
  • 如何将canvas已经绘制出来的内容进行缩放 在缩放后还能够继续进行绘制 谢谢大佬帮助!
  • 目前使用canvas在surfaceview上画路径 需要对路径进行缩放处理 所以想把canvas画的图放在bitmap上进行缩放处理 但是 使用canvas(bitmap)后,画出来的点,并没有显示在bitmap上是什么原因呀

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 105,103
精华内容 42,041
关键字:

androidcanvas