安卓通过SurfaceView类实现手写功能(下)

来源:互联网 发布:vue.js 2.0 radio 编辑:程序博客网 时间:2024/05/19 22:48

2.5 处理手写动作

可以通过SurfaceView类的派生类来实现触屏(手写)动作的处理。也可以直接重写MainActivity类的onTouchEvent()方法来处理手写动作。当MainActivity下的所有视图(控件)都没有处理触屏(手写)动作时,该方法将会被调用。

该方法的格式是

public boolean onTouchEvent(MotionEvent event)

该方法的参数event是要处理的触屏事件。

2.5.1 获取手写点的坐标

onTouchEvent()方法中,首先获取手写点的横坐标和纵坐标。

float x = event.getX();
float y = event.getY();

其中,xy分别表示手写点的横坐标和纵坐标。

2.5.2 获取手写动作的类型

对于手写的动作,可能是开始手写,也可能是在屏幕上滑动,还有可能是停止手写。对应于不同的手写动作,有不同的处理方式。

switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        break;
    case MotionEvent.ACTION_MOVE:
        break;
    case MotionEvent.ACTION_UP:
        break;
}

通过MotionEvent类的getAction()方法获取手写的动作类型。手写的动作类型主要包括ACTION_DOWN(开始手写)、ACTION_MOVE(滑动手写)、ACTION_UP(停止手写)和ACTION_CANCEL(取消手写)。

2.5.3 处理“开始手写”事件

实现手写功能,必须要将保存触屏的轨迹。使用Path类实现保存轨迹的功能。Path类可以保存直线和曲线。首先在MainActivity类中定义Path类的对象:

private Path mPath;

“开始手写”时,将手写的起始点设置为Path的起始点。在MainActivity类中添加touch_start()方法,该方法的参数为手写起始点的横纵坐标,当“开始手写”时,调用该方法。

private void touch_start(floatx, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
}

其中,reset()方法的作用是清空Path中的路径;moveTo()方法的作用是设置Path的起点;mXmY为当前触屏点的横纵坐标。

2.5.4 处理“滑动手写”事件

在处理“滑动手写”事件时,首先要判断“手写”是否已经开始“滑动”了。判断的方法是将“手写”的“滑动”位置与前一个时刻的位置进行比较,“手写”的“滑动”位置无论在横向或者纵向超出了前一个时刻的位置一个指定的距离,就可以看作是“手写”已经开始“滑动”了。此时,将该位置保存到Path类中,并且在Surface上画出来。

private void touch_move(floatx, float y) {
    float dx = Math.abs(x -mX);
    float dy = Math.abs(y -mY);
    if (dx >= TOUCH_TOLERANCE|| dy >= TOUCH_TOLERANCE) {
        mPath.quadTo(mX,mY, (x + mX)/2, (y +mY)/2);
        mX = x;
        mY = y;
    }
    mCanvas.drawPath(mPath,mPaint);
    myDraw();

}

其中,dxdy表示“手写”的“滑动”位置在横向和纵向超出了前一个时刻的位置的距离;只要这两个距离之一超出了指定距离(TOUCH_TOLERANCE),则认为“手写”已经开始“滑动”,接下来利用PathquadTo()方法将其保存,quadTo()方法的前两个参数表示前一个时刻位置的横纵坐标;后两个参数表示“手写滑动”的横纵坐标;接下来通过Canvas类将mPath中保存的路径画在位图上;最后调用自定义函数myDraw()将位图与Surface的画布(Canvas)关联,最后通知在主程序,在其Surface上显示位图。myDraw()方法见“2.5.5”。

2.5.5 在主程序的Surface上显示位图

将手写路径在位图上绘制完成后,接下来就需要在主程序的Surface上显示该位图了。在MainAcivity类中自定义一个名为myDraw()函数。

private void myDraw()
{
    Canvas canvas=surHolder.lockCanvas( );
    canvas.drawBitmap(mBitmap,0, 0,null);
    surHolder.unlockCanvasAndPost(canvas);
}

其中,surHolder是在“2.3获取SurfaceHolder”中获得到Hold了主界面上SurfaceView控件的SurfaceHolder。将已经画了背景和路径的位图绘制到SurfaceViewSurface上时,需要通过SurfaceHolder类的lockCanvas()方法来获取Surface的画布;之后通过Canvas类的drawBitmap()方法将位图绘制到Surface上;最后通过unlockCanvasAndPost()方法结束对Surface的编辑,并且通知主程序的Surface显示SurfaceView的内容。

2.6 保存手写图像

当按下“保存”按键后,将手写图像保存在SD卡中。首先获取“保存”按键的对象,之后为该按键添加点击监听器。

btnSave=(Button)findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
    @Override
    public voidonClick(View v) {
        
String sdcard ="/storage/sd_internal";
        try {
            FileOutputStream fos = new FileOutputStream(sdcard + "/manualdraw.jpeg");
            mBitmap.compress(Bitmap.CompressFormat.JPEG,100, fos);
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
});

当点击了“保存”按键后,利用FileOutputStream类和Bitmapcomress方法,将手写图像保存在内置的SD卡中,文件名为“manuldraw.jpg”。

2.7 提升权限

需要提升程序的权限才能实现将手写图像保存在内置的SD卡中的功能。在程序的“AndroidManifest.xml”中加入如下代码,以实现权限的提升。

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

原创粉丝点击