实现简单的写字板
最近在做一个项目,有一个要求就是在手机客户端上记录用户的笔迹,然后发往服务端进行笔记认证。于是就写了一个简单的绘图板,记录用户的笔迹及笔记经过的坐标值。网络连接代码暂时还没加上去。以下是代码:注释很详细的,相信大家能看懂,并希望能提出改进,谢谢!
主来,即要运行的Activity
复制代码
定制组件:MyView:
复制代码
布局文件:
复制代码
主来,即要运行的Activity
- package snowfox.android;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintStream;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- public class SimpleWrite extends Activity implements OnClickListener{
- /** Called when the activity is first created. */
- Button ok,cancer;
- MyView mv;
- Bitmap bitmap;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.simple_write);
- mv = (MyView)findViewById(R.id.MyView);
- mv.setDrawingCacheEnabled(true);
- ok = (Button)findViewById(R.id.buttonOk);
- cancer = (Button)findViewById(R.id.buttonCancer);
- ok.setOnClickListener(this);
- cancer.setOnClickListener(this);
- }
- public void onClick(View v) {
- // TODO Auto-generated method stub
- switch(v.getId())
- {
- case R.id.buttonOk:
- {
- /*
- * 将Android的Bitmap对象保存成为一个文件,该类只有compress(Bitmap.CompressFormat format, int quality, OutputStream stream),
- * 可以存为png和jpg,png可能还好说,但是jpg是有损压缩会降低图片的质量,其实Google还提供了一个API在Bitmap类,通过
- * copyPixelsToBuffer(Buffer dst)这个方法来解决
- */
- //此处对图片质量要求不高,可以直接用前一种方法.
- bitmap = mv.getDrawingCache(); //获得绘图板上的bitmap资源
- //新建文件以保存图片,文件名为系统当前时间
- File imageFile = new File("/sdcard",System.currentTimeMillis() + ".png"); //若把文件保存到sdcard,须在配置文件中添加sd卡读写权限
- try
- {
- FileOutputStream fos = new FileOutputStream(imageFile); //获取文件的输出流
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); //将bitmap的内容输出到文件输出流
- fos.flush(); //刷新输出流,将输出流中数据输入文件
- fos.close();
- }
- catch (FileNotFoundException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- catch (IOException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- mv.destroyDrawingCache(); //关掉缓冲区,以使相关无用的对象内存能被回收
- //以下为轨迹记录代码
- int array[][][] = mv.cordinate;
- //清空画板,并回收内存,在此处清空画板是因为上面已经把坐标信息记录下来了,因此之前画板的相关信息已不需要,可以清除
- mv.initBiamap();
- System.gc();
- File cordinateFile = new File("/sdcard",System.currentTimeMillis() + ".txt");
- try
- {
- PrintStream fps = new PrintStream(cordinateFile);
- for(int i = 0; i < 15; i++)
- {
- for(int j = 0; j < 30; j++)
- {
- fps.print(array[i][j][0]+" ");
- fps.print(array[i][j][1]+" ");
- fps.print("\t\t");
- fps.flush();
- }
- fps.print("\r\n");
- fps.flush();
- }
- fps.close();
- }
- catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
- }
- case R.id.buttonCancer:
- {
- //此处将界面返回为初始状
- mv.initBiamap(); //重新初始化mv组件,使其成为空白画板
- System.gc();
- break;
- }
- default:
- break;
- }
- }
- }
- package snowfox.android;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.CornerPathEffect;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.graphics.PathEffect;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.GestureDetector;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.GestureDetector.OnGestureListener;
- import android.view.View.OnTouchListener;
- import android.widget.Toast;
- public class MyView extends View implements OnTouchListener,OnGestureListener
- {
- int touchNum, pressNum; //笔画坐标数, 笔画数
- int[][][] cordinate; //存储坐标的数组
- public Paint paint;
- public Path path;
- private PathEffect effect;
- Bitmap myBitmap;
- GestureDetector testGestureDetector;
- Canvas canvas;
- public MyView(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- this.initBiamap();
- this.setOnTouchListener(this);
- this.setLongClickable(true); //只有设置了此项,才能监听手势
- }
- public void initBiamap()
- {
- touchNum = 0;
- pressNum = 0;
- cordinate = new int[20][100][2]; //最大笔画数20, 最大笔画坐标数100
- canvas = new Canvas();
- paint = new Paint();
- path = new Path();
- paint.setColor(Color.BLUE);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(3);
- paint.setAntiAlias(true); //打开抗锯齿
- effect = new CornerPathEffect(10); //打开圆角效果
- testGestureDetector = new GestureDetector(this);
- }
- @Override
- protected void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
- paint.setAntiAlias(true);
- paint.setPathEffect(effect);
- canvas.drawPath(path, paint);
- invalidate(); //刷新组件,以显示当前效果
- return;
- }
- public boolean onTouch(View v, MotionEvent event)
- {
- // TODO Auto-generated method stub
- //获取笔画坐标
- float x= event.getX();
- float y = event.getY();
- Log.i("xy===========", x + " " + y+ "==================");
- cordinate[pressNum][touchNum][0] = (int)x;
- cordinate[pressNum][touchNum][1] = (int)y;
- if(touchNum == 0) //当touchNum = 0时,则为一个笔画的起点,因此将path起点移动到此点
- path.moveTo(x,y);
- else
- path.lineTo(x,y);
- touchNum++;
- //Log.i("touchNum=====", touchNum + " ");
- //Log.i("PressNum++++++++++++", pressNum + " ");
- if(touchNum == 99) //笔画过长时,停止输入,并要求重新输入
- {
- Toast.makeText(this.getContext(), "笔画过于复杂,请重新输入", Toast.LENGTH_LONG).show();
- this.initBiamap();
- }
- if(pressNum == 19) //笔画过多时,停止输入,并要求重新输入
- {
- Toast.makeText(this.getContext(), "笔画过于复杂,请重新输入", Toast.LENGTH_LONG).show();
- this.initBiamap();
- }
- if((event.getAction()) == (MotionEvent.ACTION_UP)) //手指离开屏幕时,则下一笔为新笔画起点,因此相关数据置0
- {
- touchNum = 0;
- pressNum ++;
- }
- return testGestureDetector.onTouchEvent(event);
- }
- public boolean onDown(MotionEvent e) {
- // TODO Auto-generated method stub
- return false;
- }
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY)
- {
- // TODO Auto-generated method stub
- //n++;
- //touchNum = 0;
- //onDraw(canvas)
- return false;
- }
- public void onLongPress(MotionEvent e) {
- // TODO Auto-generated method stub
- }
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
- float distanceY) {
- // TODO Auto-generated method stub
- return false;
- }
- public void onShowPress(MotionEvent e) {
- // TODO Auto-generated method stub
- }
- public boolean onSingleTapUp(MotionEvent e) {
- // TODO Auto-generated method stub
- return false;
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background = "#c0c0c0"
- >
- <snowfox.android.MyView
- android:layout_width = "wrap_content"
- android:layout_height = "wrap_content"
- android:id = "@+id/MyView"
- android:layout_weight = "12"
- android:background = "#ffffff"
- />
- <RelativeLayout
- android:layout_width = "fill_parent"
- android:layout_height = "wrap_content"
- android:layout_gravity="bottom"
- android:layout_weight = "1">
- <Button
- android:id = "@+id/buttonOk"
- android:layout_width = "wrap_content"
- android:layout_height = "wrap_content"
- android:text = "确定"
- android:layout_alignParentLeft = "true"
- />
- <Button
- android:id = "@+id/buttonCancer"
- android:layout_width = "wrap_content"
- android:layout_height = "wrap_content"
- android:text = "取消"
- android:layout_alignParentRight = "true"
- />
- </RelativeLayout>
- </LinearLayout>