zoukankan      html  css  js  c++  java
  • Android自定义长按事件

     Android系统自带了长按事件,setOnLongClickListener即可监听。但是有时候,你不希望用系统的长按事件,比如当希望长按的时间更长一点的时候。这时候就需要自己来定义这个长按事件了。
        下面是去年我写代码的时候,自定义长按事件的方式:

    Java代码  收藏代码
    1. package chroya.fun;  
    2.   
    3. import android.content.Context;  
    4. import android.view.MotionEvent;  
    5. import android.view.View;  
    6. import android.view.ViewConfiguration;  
    7.   
    8. public class LongPressView1 extends View{  
    9.     private int mLastMotionX, mLastMotionY;  
    10.     //是否移动了  
    11.     private boolean isMoved;  
    12.     //是否释放了  
    13.     private boolean isReleased;  
    14.     //计数器,防止多次点击导致最后一次形成longpress的时间变短  
    15.     private int mCounter;  
    16.     //长按的runnable  
    17.     private Runnable mLongPressRunnable;  
    18.     //移动的阈值  
    19.     private static final int TOUCH_SLOP = 20;  
    20.   
    21.     public LongPressView1(Context context) {  
    22.         super(context);  
    23.         mLongPressRunnable = new Runnable() {  
    24.               
    25.             @Override  
    26.             public void run() {  
    27.                 mCounter--;  
    28.                 //计数器大于0,说明当前执行的Runnable不是最后一次down产生的。  
    29.                 if(mCounter>0 || isReleased || isMoved) return;  
    30.                 performLongClick();  
    31.             }  
    32.         };  
    33.     }  
    34.   
    35.     public boolean dispatchTouchEvent(MotionEvent event) {  
    36.         int x = (int) event.getX();  
    37.         int y = (int) event.getY();  
    38.           
    39.         switch(event.getAction()) {  
    40.         case MotionEvent.ACTION_DOWN:  
    41.             mLastMotionX = x;  
    42.             mLastMotionY = y;  
    43.             mCounter++;  
    44.             isReleased = false;  
    45.             isMoved = false;  
    46.             postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());  
    47.             break;  
    48.         case MotionEvent.ACTION_MOVE:  
    49.             if(isMoved) break;  
    50.             if(Math.abs(mLastMotionX-x) > TOUCH_SLOP   
    51.                     || Math.abs(mLastMotionY-y) > TOUCH_SLOP) {  
    52.                 //移动超过阈值,则表示移动了  
    53.                 isMoved = true;  
    54.             }  
    55.             break;  
    56.         case MotionEvent.ACTION_UP:  
    57.             //释放了  
    58.             isReleased = true;  
    59.             break;  
    60.         }  
    61.         return true;  
    62.     }  
    63. }  

         代码里注释的比较清楚。主要思路是在down的时候,让一个Runnable一段时间后执行,如果时间到了,没有移动超过定义的阈值,也没有释放,则触发长按事件。在真实环境中,当长按触发之后,还需要将后来的move和up事件屏蔽掉。此处是示例,就略去了。

          下面讲讲第二种方式:

    Java代码  收藏代码
    1. package chroya.fun;  
    2.   
    3. import android.content.Context;  
    4. import android.view.MotionEvent;  
    5. import android.view.View;  
    6. import android.view.ViewConfiguration;  
    7.   
    8. public class LongPressView2 extends View{  
    9.     private int mLastMotionX, mLastMotionY;  
    10.     //是否移动了  
    11.     private boolean isMoved;  
    12.     //长按的runnable  
    13.     private Runnable mLongPressRunnable;  
    14.     //移动的阈值  
    15.     private static final int TOUCH_SLOP = 20;  
    16.   
    17.     public LongPressView2(Context context) {  
    18.         super(context);  
    19.         mLongPressRunnable = new Runnable() {  
    20.               
    21.             @Override  
    22.             public void run() {               
    23.                 performLongClick();  
    24.             }  
    25.         };  
    26.     }  
    27.   
    28.     public boolean dispatchTouchEvent(MotionEvent event) {  
    29.         int x = (int) event.getX();  
    30.         int y = (int) event.getY();  
    31.           
    32.         switch(event.getAction()) {  
    33.         case MotionEvent.ACTION_DOWN:  
    34.             mLastMotionX = x;  
    35.             mLastMotionY = y;  
    36.             isMoved = false;  
    37.             postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());  
    38.             break;  
    39.         case MotionEvent.ACTION_MOVE:  
    40.             if(isMoved) break;  
    41.             if(Math.abs(mLastMotionX-x) > TOUCH_SLOP   
    42.                     || Math.abs(mLastMotionY-y) > TOUCH_SLOP) {  
    43.                 //移动超过阈值,则表示移动了  
    44.                 isMoved = true;  
    45.                 removeCallbacks(mLongPressRunnable);  
    46.             }  
    47.             break;  
    48.         case MotionEvent.ACTION_UP:  
    49.             //释放了  
    50.             removeCallbacks(mLongPressRunnable);  
    51.             break;  
    52.         }  
    53.         return true;  
    54.     }  
    55. }  

         思路跟第一种差不多,不过,在移动超过阈值和释放之后,会将Runnable从事件队列中remove掉,长按事件也就不会再触发了。源码中实现长按的原理也基本如此。

  • 相关阅读:
    EXTJS 4.2 资料 控件之checkboxgroup的用法(静态数据)
    EXTJS 4.2 资料 控件之Window窗体相关属性的用法
    EXTJS 4.2 资料 控件之textfield文本框加事件的用法
    Entity Framework 学习笔记(一)之数据模型 数据库
    EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
    EXTJS 4.2 资料 控件之Grid 列鼠标悬停提示
    Entity Framework 学习笔记(二)之数据模型 Model 使用过程
    EXTJS 4.2 资料 控件之radiogroup 的用法
    EXTJS API
    vue移动端弹框组件,vue-layer-mobile
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4712745.html
Copyright © 2011-2022 走看看