zoukankan      html  css  js  c++  java
  • 吴裕雄--天生自然ANDROID开发学习:3.8 Gestures(手势)

    手势是:连续触碰的行为,比如左右上下滑动屏幕,又或者画一些不规则的几何图形! Android对上述两种手势行为都提供了支持:
    
    Android提供手势检测,并为手势识别提供了相应的监听器!
    Android运行开发者自行添加手势,并且提供了相应的API识别用户手势!
    
    官方API文档先:GestureDetector:http://androiddoc.qiniudn.com/reference/android/view/GestureDetector.html
    
    1.Android中手势交互的执行顺序
    1.手指触碰屏幕时,触发MotionEvent事件!
    2.该事件被OnTouchListener监听,可在它的onTouch()方法中获得该MotionEvent对象!
    3.通过GestureDetector转发MotionEvent对象给OnGestureListener
    4.我们可以通过OnGestureListener获得该对象,然后获取相关信息,以及做相关处理!
    
    2.GestureListener详解:
    
    按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
    抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。
    长按(onLongPress): 手指按在持续一段时间,并且没有松开。
    滚动(onScroll): 手指在触摸屏上滑动。
    按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。
    抬起(onSingleTapUp):手指离开触摸屏的那一刹那。
    知道了GestureListener的相关方法后,实现手势检测也很简单,步骤如下:
    
    Step 1: 创建GestureDetector对象,创建时需实现GestureListener传入
    Step 2: 将Activity或者特定组件上的TouchEvent的事件交给GestureDetector处理即可! 我们写个简单的代码来验证这个流程,即重写对应的方法:
    
    代码如下:
    
    public class MainActivity extends AppCompatActivity {
    
        private MyGestureListener mgListener;
        private GestureDetector mDetector;
        private final static String TAG = "MyGesture";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //实例化GestureListener与GestureDetector对象
            mgListener = new MyGestureListener();
            mDetector = new GestureDetector(this, mgListener);
    
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return mDetector.onTouchEvent(event);
        }
    
        //自定义一个GestureListener,这个是View类下的,别写错哦!!!
        private class MyGestureListener implements GestureDetector.OnGestureListener {
    
            @Override
            public boolean onDown(MotionEvent motionEvent) {
                Log.d(TAG, "onDown:按下");
                return false;
            }
    
            @Override
            public void onShowPress(MotionEvent motionEvent) {
                Log.d(TAG, "onShowPress:手指按下一段时间,不过还没到长按");
            }
    
            @Override
            public boolean onSingleTapUp(MotionEvent motionEvent) {
                Log.d(TAG, "onSingleTapUp:手指离开屏幕的一瞬间");
                return false;
            }
    
            @Override
            public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                Log.d(TAG, "onScroll:在触摸屏上滑动");
                return false;
            }
    
            @Override
            public void onLongPress(MotionEvent motionEvent) {
                Log.d(TAG, "onLongPress:长按并且没有松开");
            }
    
            @Override
            public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
                Log.d(TAG, "onFling:迅速滑动,并松开");
                return false;
            }
        }
    
    }
    

    3.简单的例子:下滑关闭Activity,上滑启动新的Activity
    这里就用上述的SimpleOnGestureListener来实现
    

    实现代码:
    
    public class MainActivity extends AppCompatActivity {
    
        private GestureDetector mDetector;
        private final static int MIN_MOVE = 200;   //最小距离
        private MyGestureListener mgListener;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //实例化SimpleOnGestureListener与GestureDetector对象
            mgListener = new MyGestureListener();
            mDetector = new GestureDetector(this, mgListener);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return mDetector.onTouchEvent(event);
        }
    
        //自定义一个GestureListener,这个是View类下的,别写错哦!!!
        private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float v, float v1) {
                if(e1.getY() - e2.getY() > MIN_MOVE){
                    startActivity(new Intent(MainActivity.this, MainActivity.class));
                    Toast.makeText(MainActivity.this, "通过手势启动Activity", Toast.LENGTH_SHORT).show();
                }else if(e1.getY() - e2.getY()  < MIN_MOVE){
                    finish();
                    Toast.makeText(MainActivity.this,"通过手势关闭Activity",Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        }
    
    }
    

    获得GestureLibraries对象后,就可以使用该对象提供的下述方法来做相应操作了:
    
    相关方法:
    
    public void addGesture (String entryName, Gesture gesture):添加一个名为entryName的手势
    public Set<String> getGestureEntries ():获得手势库中所有手势的名称
    public ArrayList<Gesture> getGestures (String entryName):获得entryName名称对应的全部手势
    public ArrayList<Prediction> recognize (Gesture gesture): 从当前手势库中识别与gesture匹配的全部手势
    public void removeEntry (String entryName):删除手势库中entryName名称对应的手势
    public void removeGesture (String entryName, Gesture gesture):删除手势库中entryName和gesture都匹配的手势
    public abstract boolean save ():想手势库中添加手势或从中删除手势后调用该方法保存手势库
    GestureOverlayView手势编辑组件:
    
    Android为GestureOverlayView提供了三种监听器接口,如下,一般常用的是:OnGesturePerformedListener;用于手势完成时提供响应!
    

    两个布局文件:activity_main.xml和dialog_save.xml
    
    activity_main.xml
    
    <LinearLayout 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:orientation="vertical"
        tools:context=".MainActivity">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="请在下方屏幕中绘制手势~"
            android:textSize="20sp"/>
    
    
        <!-- gestureStrokeType控制手势是否需要一笔完成,multiple表示允许多笔-->
        <android.gesture.GestureOverlayView
            android:id="@+id/gesture"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gestureStrokeType="multiple" />
    
    </LinearLayout>
    dialog_save.xml
    
    <?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"
            android:orientation="horizontal">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="8dp"
                android:text="请填写手势名称:"/>
            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/edit_name"/>
        </LinearLayout>
    
        <ImageView
            android:id="@+id/img_show"
            android:layout_width="128dp"
            android:layout_height="128dp"
            android:layout_marginTop="10dp"/>
    
    </LinearLayout>
    MainActivity.java:
    
    public class MainActivity extends AppCompatActivity {
    
        private EditText editText;
        private GestureOverlayView gesture;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //获取手势编辑组件后,设置相关参数
            gesture = (GestureOverlayView) findViewById(R.id.gesture);
            gesture.setGestureColor(Color.GREEN);
            gesture.setGestureStrokeWidth(5);
            gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
                @Override
                public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) {
                    View saveDialog = getLayoutInflater().inflate(R.layout.dialog_save,null,false);
                    ImageView img_show = (ImageView) saveDialog.findViewById(R.id.img_show);
                    final EditText edit_name = (EditText) saveDialog.findViewById(R.id.edit_name);
                    Bitmap bitmap = gesture.toBitmap(128,128,10,0xffff0000);
                    img_show.setImageBitmap(bitmap);
                    new AlertDialog.Builder(MainActivity.this).setView(saveDialog)
                            .setPositiveButton("保存",new DialogInterface.OnClickListener()
                            {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    //获取文件对应的手势库
                                    GestureLibrary gestureLib = GestureLibraries.fromFile("/mnt/sdcard/mygestures");
                                    gestureLib.addGesture(edit_name.getText().toString(),gesture);
                                    gestureLib.save();
                                }
                            }).setNegativeButton("取消", null).show();
                }
            });
        }
    }
    最后还需要在AndroidManifest.xml中添加写入SD卡的权限:
    
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    6.手势识别示例
    实现代码:
    
    public class MainActivity extends AppCompatActivity {
    
        private GestureOverlayView gesture;
        private GestureLibrary gestureLibrary;
        private Context mContext;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mContext = MainActivity.this;
            gestureLibrary = GestureLibraries.fromFile("mmt/sdcard/mygestures");
            if (gestureLibrary.load()) {
                Toast.makeText(mContext, "手势库加载成功", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(mContext, "手势库加载失败", Toast.LENGTH_SHORT).show();
            }
    
            //获取手势编辑组件后,设置相关参数
            gesture = (GestureOverlayView) findViewById(R.id.gesture);
            gesture.setGestureColor(Color.GREEN);
            gesture.setGestureStrokeWidth(5);
            gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
                @Override
                public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) {
                    //识别用户刚绘制的手势
                    ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture);
                    ArrayList<String> result = new ArrayList<String>();
                    //遍历所有找到的Prediction对象
                    for (Prediction pred : predictions) {
                        if (pred.score > 2.0) {
                            result.add("与手势【" + pred.name + "】相似度为" + pred.score);
                        }
                    }
                    if (result.size() > 0) {
                        ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(mContext,
                                android.R.layout.simple_dropdown_item_1line, result.toArray());
                        new AlertDialog.Builder(mContext).setAdapter(adapter,null).setPositiveButton("确定",null).show();
                    }else{
                        Toast.makeText(mContext,"无法找到匹配的手势!",Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
    另外别忘了在AndroidManifest.xml文件中加入读SD卡的权限:
    
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    

      

  • 相关阅读:
    Insus Meta Utility
    The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
    Insus Binary Utility
    asp.net实现文件下载功能
    Column 'Column Name' does not belong to table Table
    程序已被编译为DLL,怎样去修改程序功能
    如何在Web网站实现搜索功能
    如何把数据流转换为二进制字符串
    Asp.net更新文件夹的文件
    如何显示中文月份
  • 原文地址:https://www.cnblogs.com/tszr/p/13582955.html
Copyright © 2011-2022 走看看