一款简易画图板开发
转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
一、画图板原理
1.直线效果
画图板表面上看起来可以随用户在触摸屏上自由的绘制任意图形,但是实际上当用户在触摸屏上移动时,两次拖动事件发生点的距离很小,多条极短的直线连接起来我们肉眼看起来就是直接了。在触摸屏绘制图形时,每条直线都是从上一次拖动事件发生点画到本次拖动事件的发生点,可以借助于Android提供的Path类来实现。然后,如果程序每次都是从上次拖动事件的发生点绘一条直线到本次拖动事件的发生点,那么用户前面绘制的图形就会丢失。所以,为了保留用户之前绘制的内容,我们引用"双缓冲技术"来处理。
2.双缓冲技术
所谓双缓冲技术,即当程序需要在指定View上进行绘制时,程序并不直接绘制到该View组件上,而是先绘制到一个内存中的Bitmap图片(即为缓冲)上,等到内存中的Bitmap绘制好之后,再一次性地将Bitmap绘制到View组件上。
二、开发思路
为了实现触摸屏画图效果,我们还需要为触摸屏的拖动事件提供响应,即当接触触摸屏时先记录下上一次拖动事件发生的位置并将其作为此次拖动动作的起点;然后,在拖动事件中再次获取接触点的坐标(x,y)并将其作为曲线末端点坐标;最后,当手指离开屏幕时又会产生一个事件调用Canvas的drawPath方法绘制path路径图形并保存到缓冲Bitmap中。双缓冲技术实现:
1.定义一个缓冲Bitmap对象并在该Bitmap实现一个Canvas对象,调用缓冲Bitmap的Canvas向缓冲绘图;
Bitmap cacheBitmap= Bitmap.createBitmap(VIEW_WIDTH, VIEW_HEIGHT, Config.ARGB_8888);
new Canvas().setBitmap(cacheBitmap) //指定Canvas的位图
.drawPath(path, paint); //将图形绘制到位图中
2.调用View的Canvas将缓冲中的Bitmap对象(假设为cacheBitmap)绘制到View组件上
Paint bmpPaint = new Paint();
new Canvas().drawBitmap(cacheBitmap, 0, 0, bmpPaint) //将cacheBitmap绘制到该View组件上
.drawPath(path, paint); //沿着path路径绘制图形
三、源码实现
1.HandDraw.java:继承于View的子类
package com.example.path3;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/*实现:采用双缓冲实现画图板*/
public class DrawView extends View {
float preX;
float preY;
private Path path;
public Paint paint=null;
final int VIEW_WIDTH = 320;
final int VIEW_HEIGHT = 480;
Bitmap cacheBitmap = null; //定义一个内存中的图片,该图片将作为缓存区
Canvas cacheCanvas = null; //定义cacheCanvas上的Canvas对象
/*---------------------构造方法----------------------------*/
public DrawView(Context context, AttributeSet set)
{
super(context, set);
path = new Path();
//1.创建一个与该View相同大小的缓存区
cacheBitmap = Bitmap.createBitmap(VIEW_WIDTH, VIEW_HEIGHT, Config.ARGB_8888);
//2.设置cacheCanvas将会绘制到内存中的cacheBitmap上
cacheCanvas = new Canvas();
cacheCanvas.setBitmap(cacheBitmap);
//3.设置画笔(颜色、风格、反锯齿)
paint = new Paint(Paint.DITHER_FLAG); //创建画笔
paint.setColor(Color.RED); //画笔颜色为红色
paint.setStyle(Paint.Style.STROKE); //设置画笔风格
paint.setAntiAlias(true); //反锯齿
paint.setDither(true);
}
/*---------------------监听触摸事件----------------------------*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
//获取拖动事件的发生位置
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
path.moveTo(x, y);
preX = x;
preY = y;
break;
case MotionEvent.ACTION_MOVE:
path.quadTo(preX, preY, x, y);
preX = x;
preY = y;
break;
case MotionEvent.ACTION_UP:
cacheCanvas.drawPath(path, paint); //沿着路径绘制图形存放到cacheBitmap中
path.reset();
break;
}
invalidate();
return true; //返回true表明处理方法已经处理该事件
}
// /*--------------------绘图-------------------------*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint bmpPaint = new Paint();
//a.将cacheBitmap绘制到该View组件上
canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint);
//b.沿着path绘制
canvas.drawPath(path, paint);
}
}
2.HandDraw.java:程序主界面
package com.example.path3;
import android.graphics.BlurMaskFilter;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
public class HandDraw extends ActionBarActivity {
EmbossMaskFilter emboss;
BlurMaskFilter blur;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
emboss = new EmbossMaskFilter(new float[] {1.5f,1.5f,1.5f}, 0.6f, 6,4.2f);
blur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
//装载R.menu.hand_draw对应的菜单并添加到menu中
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.hand_draw, menu);
return true;
}
//菜单被单击后的回调方法
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
DrawView dv = (DrawView)findViewById(R.id.draw);
//判断单击的是哪个菜单项并有针对性地作出响应
switch(id)
{
//颜色设置
case R.id.red: //红色
dv.paint.setColor(Color.RED);
item.setChecked(true);
break;
case R.id.green: //绿色
dv.paint.setColor(Color.GREEN);
item.setChecked(true);
break;
case R.id.blue: //红色
dv.paint.setColor(Color.BLUE);
item.setChecked(true);
break;
//画笔大小设置
case R.id.width_1: //号画笔
dv.paint.setStrokeWidth(1);
break;
case R.id.width_2: //号画笔
dv.paint.setStrokeWidth(2);
break;
case R.id.width_5: //号画笔
dv.paint.setStrokeWidth(5);
break;
//模糊效果
case R.id.blur:
dv.paint.setMaskFilter(blur);
break;
//浮雕效果
case R.id.emboss:
dv.paint.setMaskFilter(emboss);
break;
}
return super.onOptionsItemSelected(item);
}
}
3.menu.xml:菜单布局文件
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.path3.HandDraw" >
<!-- 定义一组颜色选项菜单项 -->
<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 android:checkableBehavior="single">
<item
android:id="@+id/width_1"
android:title="@string/width1"/>
<item
android:id="@+id/width_2"
android:title="@string/width2"/>
<item
android:id="@+id/width_5"
android:title="@string/width5"/>
</group>
</menu>
</item>
<!-- -->
<item android:id="@+id/blur"
android:title="@string/blur"/>
<!-- 定义一组宽度选项菜单项 -->
<item android:id="@+id/emboss"
android:title="@string/emboss"/>
</menu>
4.main.xml:主界面布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.path3.HandDraw" >
<com.example.path3.DrawView
android:id="@+id/draw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="320px"
android:height="480px" />
</RelativeLayout>
5./res/values/string.xml:字符串资源文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">简易画板</string>
<string name="color">选择颜色</string>
<string name="color_red">红色</string>
<string name="color_green">绿色</string>
<string name="color_blue">蓝色</string>
<string name="width">画笔大小</string>
<string name="width1">1号画笔</string>
<string name="width2">2号画笔</string>
<string name="width5">3号画笔</string>
<string name="blur">模糊效果</string>
<string name="emboss">浮雕效果</string>
</resources>
效果演示: