博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android绘制基础及手写绘制实例
阅读量:5086 次
发布时间:2019-06-13

本文共 6722 字,大约阅读时间需要 22 分钟。

 

Android二维图形绘制

  Android提供了一系列用于二维绘制的APIs,当绘制2D图形时,通常有两种选择:

  1.在一个View对象中绘制。继承View类,在子类的 方法中写入自己定义的绘制代码。

  2.直接在画布(Canvas)上绘制。

 

  是一个管理绘制操作的类。

  Canvas的底层有一个,你的绘制实际上是在这个位图对象上。

  当你需要绘制某些东西的时候,你实际上需要四个基本组件:

  1.一个Bitmap来存放像素。

  2.一个Canvas来调用绘制函数,向位图中写入内容。

  3.要绘制的基本图元,如矩形(Rect), 路径(Path), 位图(BitMap),或者文字等。

  4.一个画笔(Paint),指定了绘制时所用的颜色和样式等。

 

程序实例:

  这个程序实际是ApiDemos中FingerPaint程序的一小部分,实现了用户在控件中的自由绘制。

  程序自定义的MyPaintView类继承了View类,用Path记录用户点击的轨迹,在onDraw()方法中将轨迹画出。当然这个程序中最重要的是各种触摸事件的处理。

  其中方法的作用是及时调用onDraw()方法进行绘制。

  程序更新:2013/2/28 

  首先,纠正之前犯的一个错误,就是在自定义View的子类时,应该将其基类的三个构造函数全都覆写,并在其中调用基类构造函数后进行初始化。

  之前的做法在整个布局中只有一个控件时没有问题,但是要使用xml布局文件则会出错,因为必要的构造方法没有提供,或没有在其中调用初始化方法。

  其次,使用了布局文件进行布局,加入了一个TextView显示欢迎语句,底部加入Clear按钮可以进行画面清除。

  关于画面清除我想到了两种方法:

  1.重新生成位图对象;2.Bitmap类中有一个函数,利用它把位图绘制为白色。

  应该是第二种方法比较好吧,毕竟总是重新生成对象,应该会有一些内存清理方面的问题。

  附上代码(2013/2/18版本):

  自定义View: 

MyPaintView
package com.mengexample.hellofreepaint;import android.content.Context;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;public class MyPaintView extends View{    private Resources myResources;    // 画笔,定义绘制属性    private Paint myPaint;    private Paint mBitmapPaint;    // 绘制路径    private Path myPath;    // 画布及其底层位图    private Bitmap myBitmap;    private Canvas myCanvas;    private float mX, mY;    private static final float TOUCH_TOLERANCE = 4;    // 记录宽度和高度    private int mWidth;    private int mHeight;    public MyPaintView(Context context)    {        super(context);        initialize();    }    public MyPaintView(Context context, AttributeSet attrs, int defStyle)    {        super(context, attrs, defStyle);        initialize();    }    public MyPaintView(Context context, AttributeSet attrs)    {        super(context, attrs);        initialize();    }    /**     * 初始化工作     */    private void initialize()    {        // Get a reference to our resource table.        myResources = getResources();        // 绘制自由曲线用的画笔        myPaint = new Paint();        myPaint.setAntiAlias(true);        myPaint.setDither(true);        myPaint.setColor(myResources.getColor(R.color.purple_dark));        myPaint.setStyle(Paint.Style.STROKE);        myPaint.setStrokeJoin(Paint.Join.ROUND);        myPaint.setStrokeCap(Paint.Cap.ROUND);        myPaint.setStrokeWidth(12);        myPath = new Path();        mBitmapPaint = new Paint(Paint.DITHER_FLAG);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh)    {        super.onSizeChanged(w, h, oldw, oldh);        mWidth = w;        mHeight = h;        myBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);        myCanvas = new Canvas(myBitmap);    }    @Override    public boolean onTouchEvent(MotionEvent event)    {        float x = event.getX();        float y = event.getY();        switch (event.getAction())        {        case MotionEvent.ACTION_DOWN:            touch_start(x, y);            invalidate();            break;        case MotionEvent.ACTION_MOVE:            touch_move(x, y);            invalidate();            break;        case MotionEvent.ACTION_UP:            touch_up();            invalidate();            break;        }        return true;    }    @Override    protected void onDraw(Canvas canvas)    {        super.onDraw(canvas);        // 背景颜色        // canvas.drawColor(getResources().getColor(R.color.blue_dark));        // 如果不调用这个方法,绘制结束后画布将清空        canvas.drawBitmap(myBitmap, 0, 0, mBitmapPaint);        // 绘制路径        canvas.drawPath(myPath, myPaint);    }    private void touch_start(float x, float y)    {        myPath.reset();        myPath.moveTo(x, y);        mX = x;        mY = y;    }    private void touch_move(float x, float y)    {        float dx = Math.abs(x - mX);        float dy = Math.abs(y - mY);        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)        {            myPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);            mX = x;            mY = y;        }    }    private void touch_up()    {        myPath.lineTo(mX, mY);        // commit the path to our offscreen        // 如果少了这一句,笔触抬起时myPath重置,那么绘制的线将消失        myCanvas.drawPath(myPath, myPaint);        // kill this so we don't double draw        myPath.reset();    }    /**     * 清除整个图像     */    public void clear()    {        // 清除方法1:重新生成位图        // myBitmap = Bitmap        // .createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);        // myCanvas = new Canvas(myBitmap);        // 清除方法2:将位图清除为白色        myBitmap.eraseColor(myResources.getColor(R.color.white));        // 两种清除方法都必须加上后面这两步:        // 路径重置        myPath.reset();        // 刷新绘制        invalidate();    }}

  Activity:

Activity
package com.mengexample.hellofreepaint;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;import android.widget.Button;public class PaintActivity extends Activity{    Button clearBtn;    MyPaintView paintView;    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        // 将自定义的控件类作为整个布局        //setContentView(new MyPaintView(this));                //使用布局文件        setContentView(R.layout.activity_paint);                paintView = (MyPaintView) findViewById(R.id.view_paint);                clearBtn = (Button)findViewById(R.id.btn_clear);        clearBtn.setOnClickListener(new View.OnClickListener()        {                        @Override            public void onClick(View v)            {                paintView.clear();                            }        });    }    @Override    public boolean onCreateOptionsMenu(Menu menu)    {        getMenuInflater().inflate(R.menu.activity_paint, menu);        return true;    }}

  布局文件:

activity_paint.xml

 

  附上一些颜色值,这里虽然没怎么用到,但以后可以复用:

colors.xml
#f00
#0f0
#0000ff
#000
#33b5e5
#0099cc
#aa66cc
#9933cc
#99cc00
#669900
#ffbb33
#ff8800
#ff4444
#cc0000

   程序运行如图(我自己手写的Hello Wind,比较幼稚,哈~):

  

  程序还可进一步改进,加入调色板、橡皮擦、清除、形状选择与绘制、线型选择等功能,变成一个完善的画图程序。

 

参考资料:

  API DEMOS: FingerPaint

  API Guides: Canvas and Drawables

  

 

转载于:https://www.cnblogs.com/mengdd/archive/2013/02/27/2935811.html

你可能感兴趣的文章
域名解析
查看>>
ASP.NET Core 开发-缓存(Caching)
查看>>
sql获取每门课程成绩最好的学生信息
查看>>
JAVA Calendar具体解释
查看>>
网络编程
查看>>
[answer] 设$E$是赋范线性空间,$L$是$E$的真闭子空间,证明$L$在$E$中是稀疏集
查看>>
jvm学习006 jvm内存结构分配
查看>>
mobile 更改hosts
查看>>
java父类子类代码
查看>>
linux环境搭建前期配置
查看>>
null值与(NULL)的区别
查看>>
C++ pointer
查看>>
实验四 数据库查询
查看>>
ie下使用frameset布局导致跨域cookie丢失问题解决
查看>>
2019.3.6错误经验
查看>>
题解 P1886 【滑动窗口】
查看>>
矩阵求导
查看>>
bzoj 2783: [JLOI2012]树【树上差分】
查看>>
BZOJ 1497--最大获利(最小割)
查看>>
线段树模板
查看>>