当前位置: 代码迷 >> Android >> Android实战技能之二十九:画布Canvas
  详细解决方案

Android实战技能之二十九:画布Canvas

热度:99   发布时间:2016-04-28 01:06:20.0
Android实战技巧之二十九:画布Canvas

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

而这其中Canvas是比较重要的一环,今天就来演示Canvas的基本使用方法。

一、基本的draw方法

android.graphics.Canvas类提供了很多“画“的方法,让这块画布具有了丰富多彩的画画能力。比如:画点、线、矩形、椭圆、圆、文字等等。下面的例子演示了这些方法的使用。
先来建一个类,继承自View。让画布铺在View上而显示出来(这也是自定义UI组件的路子)。
重载onDraw方法,让这些画画的步骤在onDraw中完成。
源码如下:

package com.lazytech.canvasdemo;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.setStyle(Paint.Style.STROKE);        paint.setStrokeWidth(10);        canvas.drawCircle(120, 80, 60, paint);        //paint string        paint = new Paint();        paint.setColor(Color.YELLOW);        paint.setTextSize(20);        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);    }}

只要在Activity的布局文件中加上这个view就可以了。如下:

    <com.lazytech.canvasdemo.PaintBoard        android:id="@+id/paint_board"        android:layout_width="match_parent"        android:layout_below="@id/text"        android:layout_height="200dp"        android:background="@android:color/holo_green_light"        />

二、一个画板

有了上面的基础,我们就可以发挥一下,写一个画板的demo。随着手指的滑动,屏幕上留下了你艺术的痕迹。那么这个画板要如何实现呢?
有几个点要抓住:
* 捕捉你手指的滑动轨迹。重载onTouchEvent方法来实现。
* 实时更新你的画图。用invalidate方法来通知onDraw重绘。
* 保存我们的作品。将bitmap保存成文件。

有了上述要点整理,我们开始工作吧。首先还是建一个画板类PaintBoard2继承自View。三个重要元素作为类成员并在构造函数中做初始化。

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(TAG,"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);        }    }

它是如何在Activity中调用的呢?
activity的layout:

    <com.lazytech.canvasdemo.PaintBoard2        android:id="@+id/paint_board2"        android:layout_below="@id/paint_board"        android:layout_width="match_parent"        android:layout_height="200dp" />    <Button        android:id="@+id/btn_save"        android:text="Save"        android:layout_below="@id/paint_board2"        android:onClick="OnSaveClicked"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />

定义PaintBoard2作为Activity的成员,并在onCreate初始化:

private PaintBoard2 paintBoard2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        paintBoard2 = (PaintBoard2)findViewById(R.id.paint_board2);    }

点击保存按钮的处理:

    public void OnSaveClicked(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(this, "save success", Toast.LENGTH_SHORT).show();        } catch (Exception e) {            Toast.makeText(this, "save failed", Toast.LENGTH_SHORT).show();            e.printStackTrace();        }

截图风采:
这里写图片描述

完成源码参考我的开源demo项目:
https://code.csdn.net/lincyang/androidwidgetdemo

参考:
http://www.cnblogs.com/menlsh/archive/2012/11/18/2776003.html
http://www.cnblogs.com/wuyou/p/3658691.html

1楼gsd1411lxg14小时前
接收器呢
  相关解决方案