画布Canvas的初识以及一个简单画板的构造

来源:互联网 发布:淘宝大联盟 编辑:程序博客网 时间:2024/06/07 21:49

Android Framework提供了一些2D画图的API,android.graphics包就是其中之一。 
为了画一些东西,需要4个元素(或称组件)协同来完成: 
* 位图:Bitmap来保持(hold)那些像素 
* 画布:Canvas来响应画画(draw)的调用(并将其写入bitmap) 
* 画笔:paint描述画画的颜色和样式等 
* “颜料“:drawing primitive,比如矩形、路径、文字、位图等其他元素

而这其中Canvas是比较重要的一环

 下面的列表提供了对可用的基本图形的简要说明,但并没有深入地探讨每一个draw方法的详细内容: 
          drawARGB / drawRGB / drawColor   使用单一的颜色填充画布。 
          drawArc   在一个矩形区域的两个角之间绘制一个弧。 
          drawBitmap   在画布上绘制一个位图。可以通过指定目标大小或者使用一个矩阵来改变目标位图的外观。 
          drawBitmapMesh   使用一个mesh(网)来绘制一个位图,它可以通过移动网中的点来操作目标的外观。 
          drawCircle   以给定的点为圆心,绘制一个指定半径的圆。 
          drawLine(s)   在两个点之间画一条(多条)直线。 
          drawOval   以指定的矩形为边界,画一个椭圆。 
          drawPaint   使用指定的Paint填充整个Canvas 
          drawPath   绘制指定的Path。Path对象经常用来保存一个对象中基本图形的集合。 
          drawPicture   在指定的矩形中绘制一个Picture对象。 
          drawPosText   绘制指定了每一个字符的偏移量的文本字符串。 
          drawRect   绘制一个矩形。 
          drawRoundRect   绘制一个圆角矩形。 
          drawText   在Canvas上绘制一个文本串。文本的字体、大小和渲染属性都设置在用来渲染文本的Paint对象中。 
          drawTextOnPath   在一个指定的path上绘制文本。 
          drawVertices   绘制一系列三角形面片,通过一系列顶点来指定它们。 


下面来给出一个例子,先来建一个类,继承自View。让画布铺在View上而显示出来(这也是自定义UI组件的路子)。 
重载onDraw方法,让这些画画的步骤在onDraw中完成。 
源码如下:


public class PaintBoard extends View {    public PaintBoard(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //paint a circle        Paint paint = new Paint();        paint.setColor(Color.BLUE);
paint.setAntiAlias(false);       //设置画笔为无锯齿
paint.setStyle(Paint.Style.STROKE); //空心效果  
  paint.setStrokeWidth(10);//设置圆心宽度        
     //参数分别是        //x y  半径 画笔        
       canvas.drawCircle(120, 80, 60, paint);       
      //paint string       
      paint = new Paint();      
      paint.setColor(Color.YELLOW);        
          paint.setTextSize(50);       
       canvas.drawText("My name is Linc!",245,140,paint);        
      //draw line       
     paint = new Paint();     
      paint.setColor(Color.BLACK);       
      canvas.drawLine(245,145,500,145,paint);    }}


下面介绍简单画板的构造

public class PaintBoard2 extends View{    private Paint mPaint = null;    private Bitmap mBitmap = null;    private Canvas mBitmapCanvas = null;    public PaintBoard2(Context context, AttributeSet attrs) {        super(context, attrs);        mBitmap = Bitmap.createBitmap(500,200, Bitmap.Config.ARGB_8888);        mBitmapCanvas = new Canvas(mBitmap);        mBitmapCanvas.drawColor(Color.GRAY);        mPaint = new Paint();        mPaint.setColor(Color.RED);        mPaint.setStrokeWidth(6);    }//    随着手指滑动去画线:    private float startX;    private float startY ;    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                startX = event.getX();                startY = event.getY();                break;            case MotionEvent.ACTION_MOVE:                float stopX = event.getX();                float stopY = event.getY();                Log.e("jdfffff","onTouchEvent-ACTION_MOVE\nstartX is "+startX+                        " startY is "+startY+" stopX is "+stopX+ " stopY is "+stopY);                mBitmapCanvas.drawLine(startX, startY, stopX, stopY, mPaint);                startX = event.getX();                startY = event.getY();                invalidate();//call onDraw()                break;        }        return true;    }//    在onDraw时画bitmap:    @Override    protected void onDraw(Canvas canvas) {        if(mBitmap != null) {            canvas.drawBitmap(mBitmap, 0, 0, mPaint);        }    }//    提供一个将bitmap存入OutputStream的方法供保存位图做准备。    public void saveBitmap(OutputStream stream) {        if (mBitmap != null) {            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);        }    }}

下面给出存储画板图片的方法

button.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View view) {        try {            File file = new File(Environment.getExternalStorageDirectory(),                    System.currentTimeMillis() + ".jpg");            OutputStream stream = new FileOutputStream(file);            paintBoard2.saveBitmap(stream);            stream.close();            // send broadcast to Media to update data            Intent intent = new Intent();            intent.setAction(Intent.ACTION_MEDIA_MOUNTED);            intent.setData(Uri.fromFile(Environment                    .getExternalStorageDirectory()));            sendBroadcast(intent);            Toast.makeText(Main2Activity.this, "save success", Toast.LENGTH_SHORT).show();        } catch (Exception e) {            Toast.makeText(Main2Activity.this, "save failed", Toast.LENGTH_SHORT).show();            e.printStackTrace();        }    }});

O(∩_∩)O哈哈~还是蛮好玩的


当然这里你也许会遇到一些问题

比如权限问题  也许你觉得这里加个权限就没问题 了

但是到了Android4.4就不灵了,Google将MEDIA_MOUNTED的权限提高了,于是就报了一个下面的错误。

W/System.err﹕java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from 

pid=18338, uid=10087


解决办法

在stackoverfollow中找到了一个办法,在高版本中使用ACTION_MEDIA_SCANNER_SCAN_FILE去通知系统重新扫描文件。代码如下:

File file = new File(Environment.getExternalStorageDirectory(),        System.currentTimeMillis()+"ww" + ".jpg");OutputStream stream = new FileOutputStream(file);paintBoard2.saveBitmap(stream);stream.close();// send broadcast to Media to update data
//主要在这里进行一些判断if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {    Intent mediaScanIntent = new Intent(            Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);    Uri contentUri = Uri.fromFile(file); //out is your output file    mediaScanIntent.setData(contentUri);    Main2Activity.this.sendBroadcast(mediaScanIntent);}else {    Intent intent = new Intent();    intent.setAction(Intent.ACTION_MEDIA_MOUNTED);    intent.setData(Uri.fromFile(Environment            .getExternalStorageDirectory()));    sendBroadcast(intent);}


0 0