• 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掉,长按事件也就不会再触发了。源码中实现长按的原理也基本如此。

  • 相关阅读:
    Control.CheckForIllegalCrossThreadCalls
    c#禁止Webbrowser控件的弹出脚本错误对话框
    c#,WebBrowser 判断网页是否加载完毕
    c#里的动态数组ArrayList
    C#数据类型转换
    Net2.0 的新线程 ParameterizedThreadStart &BackgroundW
    在C#中使用委托的方式触发事件
    ASP.NET运行原理
    第六讲:ObjC 内存管理4 自动释放池
    第二讲:ObjC 点语法
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4712745.html
Copyright © 2020-2023  润新知