zoukankan      html  css  js  c++  java
  • 【Android】Gesture Detector

    Gesture detector

      Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等。

      这些Gesture会使用户体验大大提升。Android中的Gesture识别(detector)是通过GestureDetector.OnGestureListener接口实现的。

    1. Android事件处理机制是基于Listener实现的,比如触摸屏相关的事件,就是通过onTouchListener实现;
    2. 所有View的子类都可以通过setOnTouchListener()、setOnKeyListener()等方法来添加对某一类事件的Listener;
    3. Listener一般会以Interface的方式来提供,其中包含一个或多个abstract方法,我们需要实现这些方法来完成onTouch()、onKey()等操作。这样,程序便可以在特定的事件被dispatch到该view的时候,通过callback函数给予适当的响应。

    Touch Screen Click Demo

    public class MyGesture extends Activity implements OnTouchListener
    {
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView tv = (TextView) findViewById(R.id.tv);
            tv.setOnTouchListener(this);
        }
    
        public boolean onTouch(View v, MotionEvent event)
        {
            Toast.makeText(this, "Touch Touch", Toast.LENGTH_SHORT).show();
            return false;
        }
    }
    View Code

      可以通过MotionEvent的getAction()方法来获取Touch事件的类型,包括 ACTION_DOWN(按下触摸屏), ACTION_MOVE(按下触摸屏后移动受力点), ACTION_UP(松开触摸屏)和ACTION_CANCEL(不会由用户直接触发)。

      借助对于用户不同操作的判断,结合getRawX()、getRawY()、getX()和getY()等方法来获取坐标后,可以实现诸如拖动某一个按钮,拖动滚动条等功能。

    detector Gesture

      这里需要GestureDetector.OnGestureListener接口的帮助

    public class MyGesture extends Activity implements OnTouchListener, OnGestureListener
    {
        private GestureDetector mGestureDetector;
    
        public MyGesture()
        {
            mGestureDetector = new GestureDetector(this);
        }
    
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView tv = (TextView) findViewById(R.id.tv);
            tv.setOnTouchListener(this);
            tv.setFocusable(true);
            tv.setClickable(true);
            tv.setLongClickable(true);
            mGestureDetector.setIsLongpressEnabled(true);
        }
    
        /*
         * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,
         * 将捕捉到的MotionEvent交给GestureDetector 来分析是否有合适的callback函数来处理用户的手势
         */
        public boolean onTouch(View v, MotionEvent event)
        {
            return mGestureDetector.onTouchEvent(event);
        }
    
        // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
        public boolean onDown(MotionEvent arg0)
        {
            Log.i("MyGesture", "onDown");
            Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();
            return true;
        }
    
        /*
         * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
         * 注意和onDown()的区别,强调的是没有松开或者拖动的状态
         */
        public void onShowPress(MotionEvent e)
        {
            Log.i("MyGesture", "onShowPress");
            Toast.makeText(this, "onShowPress", Toast.LENGTH_SHORT).show();
        }
    
        // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
        public boolean onSingleTapUp(MotionEvent e)
        {
            Log.i("MyGesture", "onSingleTapUp");
            Toast.makeText(this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
            return true;
        }
    
        // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
        {
            Log.i("MyGesture", "onFling");
            Toast.makeText(this, "onFling", Toast.LENGTH_LONG).show();
            return true;
        }
    
        // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
        {
            Log.i("MyGesture", "onScroll");
            Toast.makeText(this, "onScroll", Toast.LENGTH_LONG).show();
            return true;
        }
    
        // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
        public void onLongPress(MotionEvent e)
        {
            Log.i("MyGesture", "onLongPress");
            Toast.makeText(this, "onLongPress", Toast.LENGTH_LONG).show();
        }
    }
    View Code

    Fling detector

      除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,还可以根据用户在X轴或者Y轴上的移动速度作为条件。

      比如下面的代码中就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
    {
        // 参数解释:
        // e1:第1个ACTION_DOWN MotionEvent
        // e2:最后一个ACTION_MOVE MotionEvent
        // velocityX:X轴上的移动速度,像素/秒
        // velocityY:Y轴上的移动速度,像素/秒
    
        // 触发条件 :
        // X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒
        
        final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;
        if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) 
        {
            // Fling left
            Log.i("MyGesture", "Fling left");
            Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();
        } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) 
        {
            // Fling right
            Log.i("MyGesture", "Fling right");
            Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();
        }
        return false;
    }
    View Code

      tv.setLongClickable( true )是必须的,因为 只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN)

      同样可以通过layout定义中的android:longClickable来做到这一点。

    SimpleOnGestureListener

    public class MyGesture extends Activity implements OnTouchListener
    {
        private GestureDetector mGestureDetector;
    
        public MyGesture()
        {
            mGestureDetector = new GestureDetector(new MySimpleGesture());
        }
    
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView tv = (TextView) findViewById(R.id.tv);
            tv.setOnTouchListener(this);
            tv.setFocusable(true);
            tv.setClickable(true);
            tv.setLongClickable(true);
        }
    
        public boolean onTouch(View v, MotionEvent event)
        {
            if (event.getAction() == MotionEvent.ACTION_UP)
            {
                Log.i("MyGesture", "MotionEvent.ACTION_UP");
            }
            return mGestureDetector.onTouchEvent(event);
        }
    
        // SimpleOnGestureListener implements GestureDetector.OnDoubleTapListener,
        // GestureDetector.OnGestureListener
        private class MySimpleGesture extends SimpleOnGestureListener
        {
            // 双击的第二下Touch down时触发
            public boolean onDoubleTap(MotionEvent e)
            {
                Log.i("MyGesture", "onDoubleTap");
                return super.onDoubleTap(e);
            }
    
            // 双击的第二下Touch down和up都会触发,可用e.getAction()区分
            public boolean onDoubleTapEvent(MotionEvent e)
            {
                Log.i("MyGesture", "onDoubleTapEvent");
                return super.onDoubleTapEvent(e);
            }
    
            // Touch down时触发
            public boolean onDown(MotionEvent e)
            {
                Log.i("MyGesture", "onDown");
                return super.onDown(e);
            }
    
            // Touch了滑动一点距离后,up时触发
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
            {
                Log.i("MyGesture", "onFling");
                return super.onFling(e1, e2, velocityX, velocityY);
            }
    
            // Touch了不移动一直Touch down时触发
            public void onLongPress(MotionEvent e)
            {
                Log.i("MyGesture", "onLongPress");
                super.onLongPress(e);
            }
    
            // Touch了滑动时触发
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
            {
                Log.i("MyGesture", "onScroll");
                return super.onScroll(e1, e2, distanceX, distanceY);
            }
    
            /*
             * Touch了还没有滑动时触发 (1)onDown只要Touch Down一定立刻触发 (2)Touch
             * Down后过一会没有滑动先触发onShowPress再触发onLongPress So: Touch Down后一直不滑动,onDown
             * -> onShowPress -> onLongPress这个顺序触发。
             */
            public void onShowPress(MotionEvent e)
            {
                Log.i("MyGesture", "onShowPress");
                super.onShowPress(e);
            }
    
            /*
             * 两个函数都是在Touch Down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touch Up时触发
             * 点击一下非常快的(不滑动)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed
             * 点击一下稍微慢点的(不滑动)Touch Up:
             * onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
             */
            public boolean onSingleTapConfirmed(MotionEvent e)
            {
                Log.i("MyGesture", "onSingleTapConfirmed");
                return super.onSingleTapConfirmed(e);
            }
    
            public boolean onSingleTapUp(MotionEvent e)
            {
                Log.i("MyGesture", "onSingleTapUp");
                return super.onSingleTapUp(e);
            }
        }
    }
    View Code
  • 相关阅读:
    Oracle Core 学习笔记二 Transactions 和 Consistency 说明
    Oracle AUTO_SPACE_ADVISOR_JOB 说明
    Windows 下 ftp 上传文件 脚本
    Oracle 11g 中 Direct path reads 特性 说明
    Linux 使用 wget 下载 Oracle 软件说明
    Oracle 10g read by other session 等待 说明
    Oracle 11g RAC INS06006 Passwordless SSH connectivity not set up between the following node(s) 解决方法
    SecureCRT 工具 上传下载数据 与 ASCII、Xmodem、Ymodem 、Zmodem 说明
    Oracle RAC root.sh 报错 Timed out waiting for the CRS stack to start 解决方法
    Oracle RESETLOGS 和 NORESETLOGS 区别说明
  • 原文地址:https://www.cnblogs.com/lcw/p/3482791.html
Copyright © 2011-2022 走看看