Android OnTouchListener自定义 onTouch完全解析

做android开发对touch事件是要清晰明了的,如果心存疑问,那么本博客
可以帮你清晰的屡清楚源码是如果实现
onLongClickListener onDoubleClickListener onClickListener
并且再次基础上我们可以随意添加我们想要的事件

例如:长按抬起 长按超过三秒 长按移动到view之外等事件

有了这个再也不怕产品的各种触摸事件了

初步了解MotionEvent

    public static final int ACTION_DOWN             = 0;单点触摸动作
    public static final int ACTION_UP               = 1;单点触摸离开动作
    public static final int ACTION_MOVE             = 2;触摸点移动动作
    public static final int ACTION_CANCEL           = 3;触摸动作取消
     public static final int ACTION_OUTSIDE         = 4;触摸动作超出边界
    public static final int ACTION_POINTER_DOWN     = 5;多点触摸动作
    public static final int ACTION_POINTER_UP       = 6;多点离开动作
    //以下是一些非touch事件
    public static final int ACTION_HOVER_MOVE       = 7;
    public static final int ACTION_SCROLL           = 8;
    public static final int ACTION_HOVER_ENTER      = 9;
    public static final int ACTION_HOVER_EXIT       = 10;

自定义onLongClickListener

API原理

http://www.2cto.com/kf/201402/276490.html
1. 满足一些先决条件。例如:当前视图非禁用状态、当前视图允许点击或者长按(详见 一、onTouchEvent整体结构)之后通过系统反馈的动作来进行判断

  1. ACTION_DOWN:当前是否为滚动视图,如果不是,当前视图先显示为按下状态,且在500毫秒后执行长按操作。

  2. ACTION_MOVE:如果手指移动出当前视图范围内,清理以上设置的所有状态,并且如果长按还没有执行不会触发

  3. ACTION_UP:如果MOVE时没有进行清理,且还没有执行长按操作,执行点击操作(详见 五、ACTION_UP)

  4. ACTION_CANCEL:清理所有状态

仿照api自定义长按事件

在Down的时候开启一个线程然后延迟300ms(长按触发的时间)后执行,然后再UP的时候判断如果按住的时间没有超过了300ms那么代码长按事件没有触发,然后执行连续点击事件的逻辑,同时删除掉Handler队列中的处理长按事件的线程,如果执行了Move事件也需要删除Handler队列里面的长按处理线程。

自定义onClickListener 单击 双击 多击事件

实现多击判断是记录点击的次数,也就是在Down的时候对点击次数+1,在Up的时候开启一个线程来等待是否在短时间内有下一次点击到来。定义了连续点击间隔时间为

private static final long CLICK_SPACING_TIME = 300;

这里利用Handler来让click线程延迟300ms执行,如果在线程还没有开始执行之前又一Down事件来了,那么在Handler的队列中删除这个线程,然后再Up里面重新往Handler里面添加一个线程来执行,这样就完成了间隔时间的等待,线程里面处理逻辑非常简单,就是把点击次数清空,然后回调一共连续点击了多少次。

自定义长按超过n秒事件

在发起长按监听的事件我们通过handler延迟n 毫秒来执行LongTimePressThread线程,在线程中执行回调,并且将longClickThreeMuch状态改为true

自定义长按超过n秒且移动到外头的事件

在ACTION_MOVE时,判断移动的点是不是在本view内,并且longClickThreeMuch状态为true,那么回调此事件

自定义长按在view 内外部抬起事件

在ACTION_UP时,首先先判断抬起的时间与最开始down的时间有没有超过设定的最大时间,超过了那么就是长按事件的抬起监听,继续判断抬起的点是不是在本view内 然后回调

资源释放 防止内存泄漏

将所有的handler post出去的线程,remove掉

源码

package com.meelive.ingkee.ui.listener;

import android.graphics.Rect;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.Calendar;

/**
 * Created by walkingmen on 2016/12/17.
 * 处理复杂的点击 长按 长按抬起 长按滑动等事件
 */

public class BeautyTouchListener implements View.OnTouchListener {
   
    private static final String TAG = "SHF";
    private OnBeautyTouchLisener mOnBeautyTouchLisener;
    private long longPressTipTime;

    public long getLongPressTipTime() {
        return longPressTipTime;
    }

    public void setLongPressTipTime(long longPressTipTime) {
        this.longPressTipTime = longPressTipTime;
    }

    public void setOnBeautyTouchLisener(OnBeautyTouchLisener onBeautyTouchLisener) {
        mOnBeautyTouchLisener = onBeautyTouchLisener;
    }

    public BeautyTouchListener() {
    }

    public BeautyTouchListener(OnBeautyTouchLisener onBeautyTouchLisener) {
        mOnBeautyTouchLisener = onBeautyTouchLisener;
    }

    private boolean touchOutside = false;
    private boolean touchInSide = false;
    private boolean longClickThreeMuch = false;
    private boolean haveTip = false;
    /**
     * ----------------
     */

    private static final long CLICK_SPACING_TIME = 300;

    private static final long LONG_PRESS_TIME = 500;


    /**
     * 当前触摸点相对于屏幕的坐标
     */

    private int mCurrentInScreenX;

    private int mCurrentInScreenY;


    /**
     * 触摸点按下时的相对于屏幕的坐标
     */

    private int mDownInScreenX;

    private int mDownInScreenY;

    /**
     * 点击次数
     */

    private int mClickCount = 0;


    /**
     * 当前点击时间
     */
    private long mCurrentClickTime;

    /**
     * 开始长按监听的时间
     */
    private long mLongClickStartTime = -1;


    private Handler mBaseHandler = new Handler();


    /**
     * 长按线程
     */

    private LongPressedThread mLongPressedThread;

    /**
     * 点击等待线程
     */

    private ClickPressedThread mPrevClickThread;
    /**
     * 长按等待三秒的进程
     */
    private LongTimePressThread mLongTimePressThread;


    @Override

    public boolean onTouch(View v, MotionEvent event) {
        //获取相对屏幕的坐标,即以屏幕左上角为原点
        float x;
        float y;

        //获取相对屏幕的坐标,即以屏幕左上角为原点

        mCurrentInScreenX = (int) event.getRawX();

        mCurrentInScreenY = (int) event.getRawY();

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                haveTip = false;
                /**----------------*/
                x = event.getRawX();
                y = event.getRawY();
                if (isInside(v, x, y)) {
                    touchInSide = true;
                    touchOutside = false;
                } else {
                    touchInSide = false;
                    touchOutside = true;
                }
                Log.i(TAG, "SHF--onTouch---> ACTION_DOWN");
                /**----------------*/

                //记录Down下时的坐标
                mDownInScreenX = (int) event.getRawX();
                mDownInScreenY = (int) event.getRawY();

                //记录当前点击的时间
                mCurrentClickTime = Calendar.getInstance().getTimeInMillis();

                //刷新长按的开始时间
                mLongClickStartTime = -1;

                //点击次数加1
               
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值