Android 之简易涂鸦板

来源:互联网 发布:简明python教程 沈洁元 编辑:程序博客网 时间:2024/05/13 08:39

没有废话,简单粗暴。

1.创建一个自定义 view

创建一个 DrawView,继承自 android.view.View 类。在这个类中,先定义所需的属性,再创建一个构造方法。

public class DrawView extends View {    private int view_width = 0;//画板宽度    private int view_height = 0;//画板高度    private float preX;//起始点的 x 坐标    private float preY;//起始点的 y 坐标    private Path path;//路径    public Paint paint = null;//画笔    Bitmap cacheBitmap = null;//定义一个内存中的图片,该图片作为缓冲区    Canvas cacheCanvas = null;//定义 cacheBitmap 上的 Canvas 对象    /*构造方法*/    public DrawView(Context context, AttributeSet set){        super(context,set);    }    /*重写 onDraw 方法*/    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);    }}

2.修改 xml 文件

修改 activity_main.xml 文件,并将自定义的 DrawView 添加到布局管理器中。

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <com.example.test.DrawView        android:id="@+id/drawView1"        android:layout_width="match_parent"        android:layout_height="match_parent" /></FrameLayout>

3.DrawView 的构造方法

在 DrawView 的构造方法中,首先获取屏幕的宽度和高度,并创建一个与该 view 相同大小的缓存区,然后创建一个新的画面,并实例化一个路径,再讲内存中的位图绘制到 cacheCanvas 中,最后实例化一个画笔,并设置画笔的相关属性。

//获取屏幕宽度        view_width = context.getResources().getDisplayMetrics().widthPixels;        //获取屏幕高度        view_height = context.getResources().getDisplayMetrics().heightPixels;        cacheBitmap = Bitmap.createBitmap(view_width,view_height, Bitmap.Config.ARGB_8888);        //创建一个新的画布        cacheCanvas = new Canvas();        path = new Path();        //在 cacheCanvas 上绘制 cacheBitmap        cacheCanvas.setBitmap(cacheBitmap);        paint = new Paint(Paint.DITHER_FLAG);        //设置默认的画笔颜色        paint.setColor(Color.RED);        //设置填充方式为描边        paint.setStyle(Paint.Style.STROKE);        //设置笔刷的图形样式        paint.setStrokeJoin(Paint.Join.ROUND);        //设置画笔转弯处的连接风格        paint.setStrokeCap(Paint.Cap.ROUND);        //设置默认的画笔的宽度        paint.setStrokeWidth(1);        //使用抗锯齿功能        paint.setAntiAlias(true);        //使用抖动效果        paint.setDither(true);

4.重写 onDraw 方法

在 DrawView 的 onDraw 方法中,设置背景颜色,绘制 cacheBitmap,绘制路径以及保存当前的状态到栈中,并调用 restore()方法恢复所保存的状态。

//设置背景颜色        canvas.drawColor(0xFFFFFFFF);        //采用默认设置创建一个画笔        Paint bmpPaint = new Paint();        //绘制cacheBitmap        canvas.drawBitmap(cacheBitmap,0,0,bmpPaint);        //绘制路径        canvas.drawPath(path,paint);        //保存 canvas 状态        canvas.save(Canvas.ALL_SAVE_FLAG);        //恢复 canvas 之前的保存状态,防止保存后对 canvas 执行的操作最后续的绘制有影响        canvas.restore();

5.重写 onTouchEvent 方法

在 DrawView 类中,重写onTouchEvent() 方法,为该视图添加触摸时间监听器,在该方法中,首先获取触摸时间发生的位置,然后应用 switch 对时间的不同状态添加响应代码,最后调用invalidate()方法更新视图。

@Override    public boolean onTouchEvent(MotionEvent event) {        //获取触摸时间发生的位置        float x = event.getX();        float y = event.getY();        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                //将绘图的起始点移到(x,y)的坐标位置                path.moveTo(x,y);                preX = x;                preY = y;                break;            case MotionEvent.ACTION_MOVE:                float dx = Math.abs(x-preX);                float dy = Math.abs(y-preY);                //判断是否在允许的范围内                if (dx>=5 || dy >= 5){                    path.quadTo(preX,preY,(x+preX)/2,(y+preY)/2);                    preX = x;                    preY = y;                }                break;            case MotionEvent.ACTION_UP:                //绘制路径                cacheCanvas.drawPath(path,paint);                path.reset();                break;        }        invalidate();        //返回 true,表示处理方法已经处理该事件        return true;    }

6.编写 clear() 方法

写一个 clear() 方法,用来实现橡皮擦功能。

 public void clear() {        //设置图形重叠时的处理方式        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));        //设置橡皮擦的宽度        paint.setStrokeWidth(50);    }

7.编写 save() 方法

写一个方法,用来保存当前的绘图。

public void save() {        try {            saveBitmap("myPicture");        }catch (IOException e){            e.printStackTrace();        }    }private void saveBitmap(String filename) throws IOException {        //创建文件对象        File file = new File("/sdcard/pictures/"+filename+".png");        //创建一个新文件        file.createNewFile();        //创建一个文件输出流对象        FileOutputStream out = new FileOutputStream(file);        //将绘图内容压缩成 PNG 格式输出到输出流对象中        cacheBitmap.compress(Bitmap.CompressFormat.PNG,100,out);        //将缓冲区的数据全部写出到输出流中        out.flush();        //关闭文件输出流对象        out.close();    }

8.设置权限

 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

9.创建 menu 资源文件

在 res 目录下,创建menu 文件夹,在 menu 文件夹下,创建 toolsmenu.xml 资源文件。

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" >    <item android:title="@string/color">        <menu >            <!-- 定义一组单选菜单项 -->            <group android:checkableBehavior="single" >                <!-- 定义子菜单 -->                <item android:id="@+id/red" android:title="@string/color_red"/>                <item android:id="@+id/green" android:title="@string/color_green"/>                <item android:id="@+id/blue" android:title="@string/color_blue"/>            </group>        </menu>    </item>    <item android:title="@string/width">        <menu >            <!-- 定义子菜单 -->            <group>                <item android:id="@+id/width_1" android:title="@string/width_1"/>                <item android:id="@+id/width_2" android:title="@string/width_2"/>                <item android:id="@+id/width_3" android:title="@string/width_3"/>            </group>        </menu>    </item>    <item android:id="@+id/clear" android:title="@string/clear"/>    <item android:id="@+id/save" android:title="@string/save"/></menu>

10.添加选项菜单

<1>重写onCreateOptionsMenu方法

在 activity 文件中,重写onCreateOptionsMenu()方法,在该方法中,实例化一个MenuInflater对象,并解析菜单资源文件。

@Override    public boolean onCreateOptionsMenu(Menu menu) {        MenuInflater menuInflater = new MenuInflater(this);        menuInflater.inflate(R.menu.toolsmenu,menu);        return super.onCreateOptionsMenu(menu);    }

<2>重写onOptionsItemSelected方法

重写onOptionsItemSelected() 方法,分别对各个菜单项被选择时做出相应的处理。

@Override    public boolean onOptionsItemSelected(MenuItem item) {        //获取自定义视图        DrawView drawView = (DrawView)findViewById(R.id.drawView1);        //取消擦除效果        drawView.paint.setXfermode(null);        //初始化画笔的宽度        drawView.paint.setStrokeWidth(1);        switch (item.getItemId()){            //设置画笔的颜色为红色            case R.id.red:                drawView.paint.setColor(Color.RED);                item.setChecked(true);                break;            //设置画笔的颜色为绿色            case R.id.green:                drawView.paint.setColor(Color.GREEN);                item.setChecked(true);                break;            //设置画笔的颜色为蓝色            case R.id.blue:                drawView.paint.setColor(Color.BLUE);                item.setChecked(true);                break;            //设置画笔的宽度为1            case R.id.width_1:                drawView.paint.setStrokeWidth(1);                break;            //设置画笔的宽度为5            case R.id.width_2:                drawView.paint.setStrokeWidth(5);                break;            //设置画笔的宽度为10            case R.id.width_3:                drawView.paint.setStrokeWidth(10);                break;            //擦除绘画            case R.id.clear:                drawView.clear();                break;            //保存绘画            case R.id.save:                drawView.save();                break;        }        return true;    }

运行,就会得到一个简易的涂鸦板,可以改变画笔颜色,画笔宽度,擦除,保存等。

真是越来越有意思了呢!