zoukankan      html  css  js  c++  java
  • Android绘图

    Android绘图方法主要有两个步骤:    

    (1)实现一个继承于View组件的类,并重写它的onDraw(Canavas canvas)方法;    

    (2)显示定义的View子类,有两种方法:a.使用一个Activity来显示View子类,即 setContentView(new MyView(this, null));b.在Acitviy的布局文件中增加"包名.View子类"元素,Activiyty通过setContentView方法来使用该布局文件。下面我们来学习下Android绘制图形的三个最重要的API工具。

     一、Android绘图三大API 1.Canvas类 
    (1)功能:Canvas代表了"依附"于指定View的画布,通过Canvas类的成员方法能够实现绘制各种图形。绘制一个图形由四部分组成:Bitmap、Canvas、Path/Rect/text等、Paint,其中Bitmap为绘制图形存放的像素位图,Canvas用于提供绘制图像方法、Paint为画笔、Path/Rect/text等分别为绘制图形的(轨迹/矩形/文本)。

    (2)构造方法 Canvas() :构造空的canvas对象 Canvas(Bitmap bitmap) :构造一个Canvas对象,并指定其bitmap (3)常用方法

    boolean clipRegion(Region region):剪切指定区域
    void drawBitmap(Bitmap bitmap, float left, float top, Paint paint):在指定点(x,y)使用指定的画笔paint绘制位图
    void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint):在指定点(x,y)绘制从源位图中"挖取"的一块
    void drawCircle(float cx, float cy, float radius, Paint paint):绘制原点为(cx,cy),半径为radius的圆
    void drawLine(float startX, float startY, float stopX, float stopY, Paint paint):绘制一条起点为(startX,startY),终点为(stopX,stopY)直线
    void drawLines(float[] pts, int offset, int count, Paint paint):绘制多条直线,其中pts为一个浮点型数组提供绘制一条直接所需的数据(4个/条),count为绘制直线的条数
    void drawOval(RectF oval, Paint paint):绘制一个椭圆,oval为绘制椭圆的矩形边界
    void drawPath(Path path, Paint paint):沿着路径path绘制图形
    void drawPoint(float x, float y, Paint paint):绘制一个点(x,y)
    void drawPoints(float[] pts, int offset, int count, Paint paint):绘制pts数组中的多个点(2个值/点)
    void drawRect(float left, float top, float right, float bottom, Paint paint):绘制一个矩形,其参数为距离屏幕边界的距离(边界为0)
    void drawRoundRect(RectF rect, float rx, float ry, Paint paint):使用指定的画笔绘制圆角矩形,其中rect为矩形边界、rx/ry分别为以矩形顶点为(0,0)相对位置圆的x半径、y半径
    void drawText(String text, float x, float y, Paint paint):以(x,y)为原点,使用指定画笔绘制文本
    void drawTextOnPath(String text, Path path, float x, float y, Paint paint):以(x,y)为原点,使用指定的画笔沿着指定路径绘制文本
    int getHeight():返回当前图层的高度
    int getWidth():返回当前绘图层的宽度
    void rotate(float degrees):对Canvas执行旋转变换;
    void setBitmap(Bitmap bitmap):指定Canvas(画布)的位图Bitmap
    void translate(float dx, float dy):相对于当前位置移动Canvas。向右移动dx距离(dx为负数即向左移动);向下移动dy距离(dy为负数即向上移动)
    void skew(float sx,float sy):对Canvas执行倾斜变换

    2.Paint类

    (1)功能:Paint代表了Canvas上的画笔,Paint类主要用于设置绘制风格,包括画笔的颜色、画笔笔触粗细、填充风格等。 

    (2)构造方法 Paint() :使用默认设置构造一个Paint对象 Paint(int flags) :使用指定flags构造一个Paint对象 Paint(Paint paint) :使用已有画笔的设置构造一个新的Paint对象

     (3)常用方法

    void reset():恢复画笔到默认配置
    void setARGB(int a, int r, int g, int b):设置画笔透明度和颜色,其参数分别代表透明度、红色、绿色、蓝色
    void setAlpha(int a):设置画笔的透明度
    void setAntiAlias(boolean aa):设置是否抗锯齿
    void setColor(int color):设置画笔的颜色
    void setFlags(int flags):设置画笔的flags(HINTING_OFF、HINTING_ON等)
    void setHinting(int mode):设置画笔的提示模式
    PathEffect setPathEffect(PathEffect effect):设置绘制路径时的路径效果(ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect)
    Rasterizer setRasterizer(Rasterizer rasterizer)
    Shader setShader(Shader shader):设置画笔的填充效果(BitmapShader, ComposeShader, LinearGradient, RadialGradient, SweepGradient)
    void setShadowLayer(float radius, float dx, float dy, int color):设置阴影效果
    void setStrokeJoin(Paint.Join join):设置画笔转弯处的连接风格(BEVEL-直线、MITER -锐角、ROUND-圆弧 )
    void setStrokeWidth(float width):设置画笔宽度
    void setStyle(Paint.Style style):设置Paint的填充风格(FILL-、FILL_AND_STROKE、STROKE )
    void setTextAlign(Paint.Align align):设置绘制文本时的文字对齐方式(CENTER -居中、LEFT-靠左、RIGHT -靠右:以(x,y)为中心)
    void setTextSize(float textSize):设置绘制文本的文字大小

    3.Path类 
    (1)功能:Android提供的Path类预先在View上将N个点连成一条"路径",然后调用Canvas的drawPath(path,paint)方法即可沿着路径绘制图形。另外,Android还提供了PathEffect来定义绘制路径图形效果,其包含ComposePathEffect、CornerPathEffect、DashPathEffect、DiscretePathEffect、PathDashPathEffect、SumPathEffect六种效果。

    (2)构造方法 Path():构造一个Path对象 Path(Path src) :从另一个Path对象构造一个新的Path对象 

    (3)常用方法

    boolean isEmpty():判定Path对象是否为空(即不包含直线或曲线),如果为空返回true
    void lineTo(float x, float y):增加一条从上一点到当前点(x,y)的直线
    void moveTo(float x, float y):设置下一个轮廓的开始点(x,y)
    void rLineTo(float dx, float dy):以坐标为参照增加一条从上一点到当前点(x,y)的直线
    void rMoveTo(float dx, float dy):以坐标为参照设置下一个轮廓的开始点(x,y)
    void reset():删除Path对象的所有直线和曲线
    void set(Path src):将当前Path对象的内容替换为对象src所包含的内容
    void setFillType(Path.FillType ft):设置路径的填充类型
    void setLastPoint(float dx, float dy):设置路径的最后一个点的坐标为(x,y)
    void transform(Matrix matrix):通过matrix转换该路径中的点
    void  close() :释放资源


    二、常见几何图形/文本的绘制方法 

    1.画笔常用设置

     (1)无填充风格 new Paint() .setAntiAlias(true);                       // 去锯齿                   

     .setColor(Color.BLUE);             // 设置画笔为蓝色                  

     .setStyle(Paint.Style.STROKE); // 设置画笔的填充风格 

    (2)有填充风格  new Paint() .setStyle(Paint.Style.FILL);    //填充整个图形区域        

     .setColor(Color.RED);          //填充颜色为红色

     (3)设置渐变器 

    Shader mShader = new LinearGradient(0,0,40,60                                            

    ,new int[] {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW}                                            

    ,null,Shader.TileMode.REPEAT); new Paint() .setShader(mShader);                  

    .setShadowLayer(45, 10, 10, Color.GRAY); 

    2.常见几何图形/文本(屏幕左上角为参考原点(0,0,屏幕边界均为0)

    ) (1)绘制圆形 :原点为(30,30),半径为30.   Canvas canvas = new Canvas();   canvas.drawCircle(30, 30, 30, paint);(2)绘制正方形:以屏幕左上角为参考原点(0,0),(左,上)=(30,30)、(右,下)=(200,200)  

    Canvas canvas = new Canvas();
      canvas.drawRect(30, 30, 200, 200, paint); 
     (3)绘制矩形  

     Canvas canvas = new Canvas();

     canvas.drawRect(10, 150, 70, 190, paint); 

    (4)绘制圆角矩形:re1为相对于屏幕为(0,0)点,坐标为(30,30)和(200,200)的矩形;(30,30)为相对矩形的四个顶点为零点绘制在矩形内部的圆点为半径x、y轴为15的=半径的圆,最后矩形四个角取与圆的公共部分。圆的半径越大,矩形四个角越圆。 

     Canvas canvas = new Canvas();
      RectF re1 = new RectF(30, 30, 200, 200);  

    canvas.drawRoundRect(re1, 15, 15, paint); 
     (5)绘制椭圆:以屏幕左上角为参照零点(0,0),2a=100-30,2b=310-260   Canvas canvas = new Canvas();
      RectF re11 = new RectF(30,260,100, 310);   canvas.drawOval(re11, paint); 
     (6)绘制三角形(借助Path类):以屏幕左上角为参照零点(0,0),起点为(10,340)、  

    Canvas canvas = new Canvas();
      Path path1 = new Path();   path1.moveTo(10, 340);   path1.lineTo(70, 340);   path1.lineTo(40, 290);   path1.close();   canvas.drawPath(path1, paint); 
     (7)绘制五角形(借助Path类)  Canvas canvas = new Canvas();
      Path path2 = new Path();   path2.moveTo(26, 360);   path2.lineTo(54, 360);   path2.lineTo(70, 392);   path2.lineTo(40, 420);   path2.lineTo(10, 392);   path2.close();   canvas.drawPath(path2, paint); (8)绘制文本:字符串起始位置为(30,30) new Paint() .setTextSize(30);            //文本字体大小                   .setShader(null);             //无阴影效果 Canvas canvas = new Canvas();
    canvas.drawText(getResources().getString(R.string.circle), 30, 30, paint); 
     3.源码实战:绘制图形 (1)继承View的子类MyView.java

    <span style="font-family:Times New Roman;"><span style="font-size:18px;">package com.example.canvaspaint;
    public class MyView extends View {
     // 1.构造方法
     public MyView(Context context, AttributeSet set) {
      super(context, set);
     }
    
     // 2.重写onDraw方法进行绘图
     @Override
     protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      // a.初始化画布、画笔
      canvas.drawColor(Color.WHITE); // 设置画布绘制成白色
      Paint paint = new Paint();
      paint.setAntiAlias(true); // 去锯齿
      paint.setColor(Color.BLUE); // 设置画笔为蓝色
      paint.setStyle(Paint.Style.STROKE); // 设置画笔的填充风格
    
      /*------------------------无填充风格绘制----------------------------*/
    
      // b.绘制圆形
      canvas.drawCircle(30, 30, 30, paint);
      // c.绘制正方形
      canvas.drawRect(10, 30, 50, 50, paint);
      // d.绘制矩形
      canvas.drawRect(30, 30, 200, 200, paint);
      // e.绘制圆角矩形
      RectF re1 = new RectF(30,30, 200, 200);
      canvas.drawRoundRect(re1, 30,30, paint);
      // f.绘制椭圆
      RectF re11 = new RectF(30,30,100, 80);
      canvas.drawOval(re11, paint);
       //g.定义一个Path对象,封闭成一个三角形并根据Path对象绘制
      Path path1 = new Path();
      path1.moveTo(10, 340);
      path1.lineTo(70, 340);
      path1.lineTo(40, 290);
      path1.close();
      canvas.drawPath(path1, paint);
      // h.根据Path绘制五角形
      Path path2 = new Path();
      path2.moveTo(26, 360);
      path2.lineTo(54, 360);
      path2.lineTo(70, 392);
      path2.lineTo(40, 420);
      path2.lineTo(10, 392);
      path2.close();
      canvas.drawPath(path2, paint);
    
      /*------------------------设置填充风格后绘制----------------------------*/
      paint.setStyle(Paint.Style.FILL);
      paint.setColor(Color.RED);
      // b.绘制圆形
      canvas.drawCircle(120, 40, 30, paint);
      // c.绘制正方形
      canvas.drawRect(90, 80, 150, 140, paint);
      // d.绘制矩形
      canvas.drawRect(90, 150, 150, 190, paint);
      // e.绘制圆角矩形
      RectF re2 = new RectF(90, 200, 70, 230);
      canvas.drawRoundRect(re2, 15, 15, paint);
      // f.绘制椭圆
      RectF re22 = new RectF(90, 240, 150, 270);
      canvas.drawOval(re22, paint);
      // g.定义一个Path对象,封闭成一个三角形并根据Path对象绘制
      Path path3 = new Path();
      path3.moveTo(90, 340);
      path3.lineTo(150, 340);
      path3.lineTo(120, 290);
      path3.close();
      canvas.drawPath(path3, paint);
      // h.根据Path绘制五角形
      Path path4 = new Path();
      path4.moveTo(106, 360);
      path4.lineTo(134, 360);
      path4.lineTo(150, 392);
      path4.lineTo(120, 420);
      path4.lineTo(90, 392);
      path4.close();
      canvas.drawPath(path4, paint);
     
    /*------------------------设置渐变器后绘制----------------------------*/
     
      Shader mShader = new LinearGradient(0,0,40,60,new int[] {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},null,Shader.TileMode.REPEAT);
      paint.setShader(mShader);
      paint.setShadowLayer(45, 10, 10, Color.GRAY);
      //b.绘制圆形
      canvas.drawCircle(200,40,30, paint);
      //c.绘制正方形
      canvas.drawRect(170,80,230,140,paint);
      //d.绘制矩形
      canvas.drawRect(170, 150, 230, 190, paint);
      //e.绘制圆角矩形
      RectF re3= new RectF(170,200,230,230);
      canvas.drawRoundRect(re3, 15, 15, paint);
      //f.绘制椭圆
      RectF re33 = new RectF(170,240,230,270);
      canvas.drawOval(re33, paint);
      //g.定义一个Path对象,封闭成一个三角形并根据Path对象绘制
      Path path5 = new Path();
      path5.moveTo(170, 340);
      path5.lineTo(230, 340);
      path5.lineTo(200, 290);
      path5.close();
      canvas.drawPath(path5, paint);
      //h.根据Path绘制五角形
      Path path6 = new Path();
      path6.moveTo(186, 360);
      path6.lineTo(241, 360);
      path6.lineTo(230, 392);
      path6.lineTo(200, 420);
      path6.lineTo(170, 392);
      path6.close();
      canvas.drawPath(path6, paint);
     
      /*---------------设置字符大小后绘制---------------*/
      paint.setTextSize(30);
      paint.setShader(null);
    //	 //绘制7个字符串
      canvas.drawText(getResources().getString(R.string.circle), 30, 30, paint);
      canvas.drawText(getResources().getString(R.string.square), 240, 120, paint);
      canvas.drawText(getResources().getString(R.string.rect), 240, 175, paint);
      canvas.drawText(getResources().getString(R.string.round_rect), 230, 220, paint);
      canvas.drawText(getResources().getString(R.string.oval), 240, 260, paint);
      canvas.drawText(getResources().getString(R.string.triangle), 240, 325, paint);
      canvas.drawText(getResources().getString(R.string.pentagon), 240, 390, paint);
     }
    }</span></span>


    (2)应用界面显示该View子类CanvasTest.java

    <span style="font-family:Times New Roman;"><span style="font-size:18px;">package com.example.canvaspaint;
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    public class CanvasTest extends ActionBarActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(new MyView(this, null));
        }
    }</span></span>

    效果演示: 

    二、Path类的使用 
    1.Path使用     Canvas沿着路径绘制图形,我们可以这样来定义一条路径:

    (1)构造一个Path对象;

    (2)调用Path的moveTo(x,y)方法设定路径的起点;

    (3)调用lineTo(x,y)方法设定下一个点的位置。 

    (1)设置Path路径效果:首先需要创建一个PathEffect子类对象,然后再调用Piant的setPathEffect(PathEffect p)方法即可。

    (2)沿着路径绘制文本:首先需要设定路径的形状,然后设置好画笔并调用Canvas的drawPath(Path path,Paint paint)方法沿着路径绘制图形,最后调用Canvas的drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)方法绘制路径文本,其中hOffset为相对于路径起点距离的水平位置,hOffset为相对于路径上或下距离。

     2.源码实战:

     (1)PathTest.java:使用PathEffect类的6个子类实现6种不同的路径绘制效果

    <span style="font-family:Times New Roman;"><span style="font-size:18px;">package com.example.android_path;
    public class PathTest extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(new MyView(this));
        }
        /*-----------------------构造方法---------------------------*/
        class MyView extends View
        {
      float phase;
         PathEffect[] effects = new PathEffect[7];
         int[] colors;
         private Paint paint;
         Path path;
         public MyView(Context context) {
       super(context);
       //1.初始化画笔Paint
       paint = new Paint();	//实例化一个(画笔)Paint对象
       paint.setStyle(Paint.Style.STROKE);	//设置Paint的填充风格
       paint.setStrokeWidth(4);
       //2.创建并初始化Path
       path = new Path();
       path.moveTo(0, 0);
       for(int i=1;i<=15;i++)
       {
        //生成15个点,随机生成它们的Y坐标,并将它们生成一条Path
        path.lineTo(i*20, (float)Math.random()*60);
       }
       //3.初始化7个颜色
       colors = new int[] {Color.BLACK,Color.RED,Color.BLUE,Color.GRAY,Color.GREEN,Color.MAGENTA,Color.YELLOW};
      } 
          /*-----------------------绘图---------------------------*/
          @Override
      protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       canvas.drawColor(Color.WHITE);	//将画布背景填充成白色
       //4.初始化7种路径效果
       effects[0]=null;	 //a.不使用路径效果
       effects[1] = new CornerPathEffect(10);	 //b.初始化CornerPathEffect
       effects[2] = new DiscretePathEffect(3.0f,5.0f);	 //c.初始化DiscretePathEffect
       effects[3] = new DashPathEffect(new float[] {20,10,5,10}, phase);	 //d.初始化DashPathEffect
       Path p = new Path();
       p.addRect(0, 0, 8, 8, Path.Direction.CCW);
       effects[4] = new PathDashPathEffect(p, 12, phase, PathDashPathEffect.Style.ROTATE);	//e.初始化PathDashPathEffect
       effects[5] = new ComposePathEffect(effects[2],effects[3]);	 //f.初始化ComposePathEffect
       effects[6] = new SumPathEffect(effects[4], effects[3]);	 //g.初始化SumPathEffect
       //5.将画布移动到(8,8)处开始绘制,依次使用7中不同路径效果、7中不同的颜色来绘制路径
       canvas.translate(8, 8);
       for(int i=0;i<effects.length;i++)
       {
        paint.setPathEffect(effects[i]);
        paint.setColor(colors[i]);
        canvas.drawPath(path, paint);
        canvas.translate(0, 60);
       }
       //6.改变phase值,形成动画效果
       phase +=1;
       invalidate();
      }
        }
    }</span></span>


    效果演示: 
     分析:在上面的程序中,当定义DashPathEffect、PathDashPathEffect时可以指定一个phase参数,该参数用于指定路径效果的相位,当该phase参数不断地变化时,程序将不停得绘制该View组件,就会产生动画效果。另外,View的invalidate()方法就是使当前的View视图失效然后再次调用View的onDraw(Canvas canvas)方法重新绘图,需要注意的是invalidate()方法只能在UI线程中使用。 (2)PathText.java:沿着路径绘制文本

    <span style="font-family:Times New Roman;"><span style="font-size:18px;">package com.example.path;
    /*沿着Path绘制文本*/
    public class PathText extends Activity {
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(new ViewText(this));
     }
    	
     class ViewText extends View
     {
      final String DRAW_STR = "何以笙箫默";
      Path[] paths = new Path[3];
      Paint paint;
      
      /*----------------------构造方法--------------------------*/
      
      public ViewText(Context context) {
       super(context);
       paths[0] = new Path();
       paths[0] .moveTo(0, 0); 
        //第一条路径:自动生成7个点连成一条线 
       for(int i=1;i<=7;i++)        
       {
         paths[0].lineTo(i*30, (float)Math.random()*30);
       }
        //第二条路径:为一个椭圆(200,120)
       paths[1] = new Path();
       RectF rectF = new RectF(0,0,200,120);
       paths[1].addOval(rectF, Path.Direction.CCW);
      //第三条路径:为一条圆弧
       paths[2] = new Path();
       paths[2].addArc(rectF, 60, 180);
       //2.初始化画笔
       paint = new Paint();
       paint.setAntiAlias(true);
       paint.setColor(Color.RED);
       paint.setStrokeWidth(1);
      }
    
      /*-------------------------绘图---------------------------------*/
      @Override
      protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       canvas.drawColor(Color.WHITE);	 //设置画布背景为白色
       canvas.translate(40, 40);
       //a.设置从右边开始绘制(右对齐)
       paint.setTextAlign(Paint.Align.RIGHT);
       paint.setTextSize(20);
       //b.绘制第一条路径
       paint.setStyle(Paint.Style.STROKE);	 //绘制路径
       canvas.drawPath(paths[0],paint);
       paint.setStyle(Paint.Style.FILL);//沿着路径绘制一段文本
       canvas.drawTextOnPath(DRAW_STR, paths[0], -8, 20, paint);
        //对Canvas进行坐标变换,画布下移120
        canvas.translate(0, 60);
       //c.绘制第二条路径
       paint.setStyle(Paint.Style.STROKE);	//绘制路径
       canvas.drawPath(paths[1], paint);
       paint.setStyle(Paint.Style.FILL);	 //沿着路径绘制一段文本
       canvas.drawTextOnPath(DRAW_STR, paths[1], -20, 20, paint);
        //对Canvas进行坐标变换,画布下移120
        canvas.translate(0, 120);
       //d.绘制第三条路径
       paint.setStyle(Paint.Style.STROKE);	//绘制路径
       canvas.drawPath(paths[2], paint);
       paint.setStyle(Paint.Style.FILL);	 //沿着路径绘制一段文本
       canvas.drawTextOnPath(DRAW_STR, paths[2], -10, 20, paint);
       
      }
      
     }
    }</span></span>

    效果演示: 

  • 相关阅读:
    $(document).ready() 与$(window).load()
    关于.NET玩爬虫这些事 【初码干货】
    关于c# .net爬虫
    UIScollView Touch事件
    UISearchBar 点击X 按钮收键盘
    IOS7 UITableView一行滑动删除后 被删除行的下一行的点击事件将被忽略解决办法
    IOS 使用dispatch_once 创建单例
    IOS 定位 单例
    IOS拷贝文件到沙盒
    IOS后台运行
  • 原文地址:https://www.cnblogs.com/xiaoxiaoshen/p/5225747.html
Copyright © 2011-2022 走看看