Android中實現自定義手勢和識別手勢的功能

Android中實現自定義手勢和識別手勢的功能

1. 先完成自定義手勢的Activity

1.1 因爲需要存儲手勢文件所以需要聲明權限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />		//讀取SD卡權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />	//寫入SD卡權限

1.2 簡單寫一個佈局文件,其中用到了GestureOverlayView,相當於一個繪製組件。其中有一個重要屬性gestureStrokeType,值爲single時表示只繪製一筆,若要多筆繪製值應該設爲multiple:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".addgesture.Main3Activity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="recognition"
        android:text="識別手勢" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="請繪製手勢" />

    <android.gesture.GestureOverlayView
        android:id="@+id/activity_main3_gov"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gestureStrokeType="multiple"	//多筆繪製
        ></android.gesture.GestureOverlayView>
</LinearLayout>

1.3 這裏自定義了AlertDialog的樣式:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="請輸入手勢名稱" />

        <EditText						//輸入手勢的名稱
            android:id="@+id/save_dialog_et"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

    <ImageView							//展示繪製的手勢
        android:id="@+id/save_dialog_iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

1.4 代碼部分:

package com.example.mygesture.addgesture;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.example.mygesture.R;
import com.example.mygesture.recognitiongesture.Main4Activity;

public class Main3Activity extends AppCompatActivity {
    GestureOverlayView gov;											//定義繪製組件

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);					
        }															//高版本需要動態申請權限
        init();
    }

    private void init() {
        gov = findViewById(R.id.activity_main3_gov);
//        gov.setGestureColor(Color.RED);							//設置繪製的顏色
        gov.setGestureStrokeWidth(4);								//設置畫筆的寬度
        gov.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {	//設置繪製完成監聽
            @Override
            public void onGesturePerformed(GestureOverlayView overlay, final Gesture gesture) {
                View saveDialog = getLayoutInflater().inflate(R.layout.save_dialog, null);		//獲取AlertDialog的佈局樣式
                final EditText editText = saveDialog.findViewById(R.id.save_dialog_et);
                ImageView imageView = saveDialog.findViewById(R.id.save_dialog_iv);
                Bitmap bitmap = gesture.toBitmap(128, 128, 10, 0xFFFF0000);						//將手勢轉換爲位圖
                imageView.setImageBitmap(bitmap);												//用ImageView加載手勢圖片
                new AlertDialog.Builder(Main3Activity.this).setView(saveDialog).setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        GestureLibrary gestureLibrary = GestureLibraries.fromFile("/mnt/sdcard/mygesture");//利用手勢庫獲取存放手勢文件的地址
                        gestureLibrary.addGesture(editText.getText().toString(), gesture);					//向手勢庫中添加手勢名稱和手勢
                        gestureLibrary.save();																//保存手勢庫
                        Toast.makeText(Main3Activity.this, "保存成功", Toast.LENGTH_SHORT).show();
                    }
                }).setNegativeButton("取消", null)
                        .show();
            }
        });
    }
    public void recognition(View view) {
        Intent intent = new Intent(this, Main4Activity.class);
        startActivity(intent);
    }
}

2. 接下來完成識別手勢的Activity:

2.1 一樣的先寫佈局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".recognitiongesture.Main4Activity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="請繪製需要識別的手勢" />

    <android.gesture.GestureOverlayView
        android:id="@+id/activity_main4_gov"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.gesture.GestureOverlayView>
</LinearLayout>

2.2 代碼的編寫

package com.example.mygesture.recognitiongesture;

import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.Prediction;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import com.example.mygesture.R;
import java.util.ArrayList;
import java.util.logging.Level;

public class Main4Activity extends AppCompatActivity {
    GestureOverlayView gov;
    GestureLibrary gestureLibrary;						//定義手勢庫
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);

        init();
    }

    private void init() {
        gestureLibrary = GestureLibraries.fromFile("/mnt/sdcard/mygesture");	//獲取手勢文件
        if (gestureLibrary.load()) {											//判斷手勢文件是否存在以及加載
            Toast.makeText(this, "手勢文件加載成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "手勢文件加載失敗", Toast.LENGTH_SHORT).show();
        }
        gov = findViewById(R.id.activity_main4_gov);
        gov.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
            @Override
            public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
                ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture);		//匹配手勢庫中的所有手勢
                ArrayList<String> result = new ArrayList<>();								//匹配結果數組
                for (Prediction pred : predictions) {
                    if (pred.score > 2) {													//匹配手勢庫中的所有手勢,並將相似度>2存入匹配結果數組
                        result.add("相似度:" + pred.score);
                    }
                }
                if (result.size() > 0) {					//這裏用了適配器來作爲AlertDialog的佈局樣式,用於顯示所有手勢的相似度
                    ArrayAdapter<Object> arrayAdapter = new ArrayAdapter<Object>(Main4Activity.this, android.R.layout.simple_dropdown_item_1line, result.toArray());
                    new AlertDialog.Builder(Main4Activity.this).setAdapter(arrayAdapter, null).setPositiveButton("確定", null).show();
                } else {
                    Toast.makeText(Main4Activity.this, "未找到與之匹配的手勢", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

3. 到這裏也算大功告成了,效果圖我就不貼了,因爲不能上傳視頻,GIF圖也不好搞。

Tip: 小白,寫得不好請見諒。若有不對的地方請留言。

關於手勢部分的功能點: Android中簡單實現頁面翻轉和自動翻轉的功能Android中實現雙指縮放的功能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章