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"/>
    

      

  • 相关阅读:
    C#项目打包,并自动安装SQL数据库(转)
    [转]将List对象列表转换成JSON格式的类
    查找算法集:顺序查找、二分查找、插值查找、动态查找(数组实现、链表实现)
    C#编码好习惯
    数据库构思与设计规范
    ASP.NET下母版页和内容页中的事件发生顺序整理
    记录要点
    div挡住select的5种方法
    html源码获取方法
    TransactionScope 分布式事务
  • 原文地址:https://www.cnblogs.com/tszr/p/13582955.html
Copyright © 2011-2022 走看看