往屏幕中加入滑动效果

  今天做了一个半屏显示的demo,加入了对于滑动效果的支持。。。用到一些滑动的知识和一些小技巧。。。

 首先要实现滑动有大概有两种方法:OnTouchListener 和 GestureDetector.OnGestureListener。。。

1,使用OnTouchListener 在onTouch方法中监听不同的touch事件,算出手指滑动的距离方向。。然后获得对应的状态就行屏幕的滑动显示

2,使用 GestureDetector.OnGestureListener方法,讲onTouch直接传递给GestureDetector.OnGestureListener方法做处理。。


View类有个View.OnTouchListener内部接口,通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,但是这个方法太过简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)。

Android sdk给我们提供了GestureDetectorGesture:手势Detector:识别)类,通过这个类我们可以识别很多的手势,主要是通过他的onTouchEvent(event)方法完成了不同手势的识别。虽然他能识别手势,但是不同的手势要怎么处理,应该是提供给程序员实现的。

个人觉得能用系统的就不用自己的,省的麻烦就省下了许多错误嘿嘿。。所以就采用了GestureDetector.OnGestureListener方法。。


认识GestureDetector.OnGestureListener

GestureDetector这个类对外提供了两个接口:OnGestureListenerOnDoubleTapListener,还有一个内部类SimpleOnGestureListener


GestureDetector.OnDoubleTapListener接口


用来通知DoubleTap事件,类似于鼠标的双击事件。

1onDoubleTap(MotionEvent e):在双击的第二下,Touch down时触发 

2onDoubleTapEvent(MotionEvent e):通知DoubleTap手势中的事件,包含downupmove事件(这里指的是在双击之间发生的事件,例如在同一个地方双击会产生DoubleTap手势,而在DoubleTap手势里面还会发生downup事件,这两个事件由该函数通知);双击的第二下Touch downup都会触发,可用e.getAction()区分。 

3onSingleTapConfirmed(MotionEvent e):用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,然后触发SingleTapConfirmed事件。这个方法不同于onSingleTapUp,他是在GestureDetector确信用户在第一次触摸屏幕后,没有紧跟着第二次触摸屏幕,也就是不是双击的时候触发  


GestureDetector.OnGestureListener接口:用来通知普通的手势事件,该接口有如下六个回调函数:
     1.  
 onDown(MotionEvent e)down事件;
     2.  
 onSingleTapUp(MotionEvent e):一次点击up事件;在touch down后又没有滑动

onScroll),又没有长按(onLongPress),然后Touchup时触发。

 点击一下非常快的(不滑动)Touchup

onDown->onSingleTapUp->onSingleTapConfirmed 
          
点击一下稍微慢点的(不滑动)Touchup

onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
     3.  
 onShowPress(MotionEvent e)down事件发生而move或则up还没发生前触发该   

事件;Touch了还没有滑动时触发(与onDownonLongPress)比较onDown只要Touch down一定立刻触发。而Touchdown后过一会没有滑动先触发onShowPress再是onLongPress。所以Touchdown后一直不滑动

按照onDown->onShowPress->onLongPress这个顺序触发。 
     4.  
 onLongPress(MotionEvent e):长按事件;Touch了不移动一直Touch down时触发 
     5.  
 onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑动手

势事件;Touch了滑动一点距离后,ACTION_UP时才会触发       

参数:e1 1ACTION_DOWN MotionEvent 并且只有一个;e2 最后一个ACTION_MOVE MotionEvent velocityX X轴上的移动速度,像素/ velocityY Y轴上的移动速度,像素/.触发条件:X轴的坐标位移大于FLING_MIN_DISTANCE且移动速度大于FLING_MIN_VELOCITY个像素/

6.   onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上

拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法在ACTION_MOVE动作发生时就会触发

        抛:手指触动屏幕后,稍微滑动后立即松开

onDown-----onScroll----onScroll----onScroll----………----->onFling

        拖动

onDown------onScroll----onScroll------onFiling

 

SimpleOnGestureListenerGestureDetector提供给我们的一个更方便的响应不同手势的类,这个类实现了上述两个接口(但是所有的方法体都是空的),该类是static class,也就是说它实际上是一个外部类。程序员可以在外部继承这个类,重写里面的手势处理方法。


使用比较简单就是在onTouch方法中调用mGestureDetector.onTouchEvent(event);


API:

  二、概述

  通过系统提供的MotionEvent来监测各种手势和(触摸)事件。当一个指定的手势事件发生时,GestureDetector.OnGestureListener回调函数将通告用户。这个类仅仅处理由触摸引发的MotionEvent(不能处理由轨迹球引发的事件)。要使用这个类需执行以下操作:

  * 为你的View建立一个GestureDetector实例。

  * ViewonTouchEvent(MotionEvent)方法里确保调用(GestureDetector的)onTouchEvent(MotionEvent)方法。当相关事件发生时,定义

回调函数里的方法将被执行。

 

  三、嵌套类

  interface          GestureDetector.OnDoubleTapListener

  双击和轻击(confirmed single-tap)事件的监听器。(译者注:confirmed single-tap是用户快速点一下触摸屏所引发的动作。区分下面两种情况:

  1.       手指按下,停留0.2秒(估计值)以上再抬起时,不算confirmed single-tap

  2.       快速点击屏幕两次不会引发两次confirmed single-tap事件,而是引发一次DoubleTap事件。)

 

  interface          GestureDetector.OnGestureListener

  在有手势动作发生时,通知的监听器

 

  class        GestureDetector.SimpleOnGestureListener         

  当只需要监听部分手势时,用于扩展的便捷类

 

  四、构造函数

public GestureDetector (GestureDetector.OnGestureListener listener, Handler handler)

通过提供的监听器来创建一个GestureDetector,这个构造函数只能用于非UI线程(因为它允许指定一个handler)。

参数

         listener 用于触发所有回调函数的监听器,不能为空

handler 需要使用到的handler

异常

         NullPointerException   Listener或者handler为空时

 

public GestureDetector (GestureDetector.OnGestureListener listener)

通过提供的监听器来创建一个GestureDetector。你只能于UI线程里使用这个构造函数(这是通常的情况)

参数

         listener    用于触发所有回调函数的监听器,不能为空

异常

    NullPointerException   如果Listener为空

参见

    Handler()

 

public GestureDetector (Context context, GestureDetector.OnGestureListener listener)

通过提供的监听器来创建一个GestureDetector。(通常情况下)你只能于UI线程里使用这个构造函数

         参数

                   context    应用程序上下文

listener    用于触发所有回调函数的监听器,不能为空

                   异常

           NullPointerException   如果Listener为空

参见

        Handler()

 

public GestureDetector (Context context, GestureDetector.OnGestureListener listener, Handler handler)

通过提供的监听器来创建一个GestureDetector. (通常情况下)你只能于UI线程里使用这个构造函数

         参数

context    应用程序上下文

listener    用于触发所有回调函数的监听器,不能为空

handler    需要使用到的handler

                   异常

           NullPointerException       如果Listener为空

参见

       Handler()

 

public GestureDetector (Context context, GestureDetector.OnGestureListener listener, Handler handler, boolean ignoreMultitouch)

通过提供的监听器来创建一个GestureDetector. (通常情况下)你只能于UI线程里使用这个构造函数

         参数

context    应用程序上下文

listener    用于触发所有回调函数的监听器,不能为空

handler    需要使用到的handler

ignoreMultitouch     是否忽视多点触控(译者注:仅适用于2.2以上的android版本,如果没设置这个参数(即使用的是上一个构造函数),则会忽视多点触控

,由于网上都没有在GestureDetector传入handler的例子,所以我也不明白这里的handler的具体用意。如果有需要深入理解的朋友,请参照GestureDetector的源码

                  异常

           NullPointerException       如果Listener为空

参见

       Handler()

 

  五、公共方法

public boolean isLongpressEnabled ()

返回值

如果允许长按事件,则返回true,否则为false

 

public boolean onTouchEvent (MotionEvent ev)

分析指定的动作事件,如何满足条件,就触发在GestureDetector.OnGestureListener中提供的回调函数

         参数

                   ev     当前的触摸事件(译者注:如MotionEvent_DOWN, MotionEvent_UP

         返回值

                   如果GestureDetector.OnGestureListener消耗了这个事件,则返回true,否则返回false

 

public void setIsLongpressEnabled (boolean isLongpressEnabled)

设置是否启用长按。如果启用长按,当用户按下并保持按下状态时,将收到一个长按事件,同时不再接收其它事件;如果禁用长按,当用户按下并保持按下状态然后再移动手指时,将会接收到scroll事件。长按默认为启用。

         参数

                   isLongpressEnabled                  是否启用接收长按事件

 

public void setOnDoubleTapListener (GestureDetector.OnDoubleTapListener onDoubleTapListener)

设置双击及其相关手势的监听器

         参数

                   onDoubleTapListener       触发所有回调函数的监听器,或者设为null以停止监听双击的手势

 

遇到的问题:

1. onFling(***)无法触发

     通过设置 mListView.setLongClickable(true);即可(我处理的是ListView的手势事件),只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。


2. 用户长按手机屏幕,就会触发长按事件,离开屏幕时,就会触发up事件,但是SimpleOnGestureListener没有对longPress事件的up事件对外提供接口

解决办法:

类似于这样,截获up事件,因为所有的都是有OnTouchListener 先获得,然后传递给SimpleOnGestureListener的,这里有一点必须要注意:

截获到up事件,我们进行了处理后,必须要将这个事件再交给SimpleOnGestureListener处理,虽然我们只截获长按事件的up,但是SimpleOnGestureListener对于长按事件的up也做了一些处理,只是没有对外提供接口。

做了什么处理:

if (mInLongPress) {
                mHandler.removeMessages(TAP);
                mInLongPress = false;

}

如果不交给SimpleOnGestureListener处理,那么单击动作也会触发onLongPress方法。

private OnTouchListener gestureTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return gDetector.onTouchEvent(event);
           case MotionEvent.ACTION_UP:
                MyGesture.FlagInfo info = mGesture.getFlagInfo();
                if(info.isConnected==true){
                    int firstVisiblePosition = mListView.getFirstVisiblePosition();
                    View view = mListView.getChildAt(info.position-firstVisiblePosition);
                    if(view!=null){
                        view.setBackgroundResource(R.drawable.listitem_background_blue);
                        info.isConnected = false;
                    }
                }
                return gDetector.onTouchEvent(event);
            case MotionEvent.ACTION_MOVE:
                return gDetector.onTouchEvent(event);
            }
            return false;
            
        }
    };

3:onScroll 方法不允许。。

解决:onDown  返回 ture。

4、onScroll 方法运行的时候,手指滑动的距离距离计算不对。

解决:onScorll是循环执行的只能获得它执行的这段时间所滑动的距离,并不能获得一次操作所滑动的距离。在onDown  方法中设置了一个变量,然后在onScroll 方法中不断累加mScrollX += distanceX;





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值