Android Button长按执行周期事件

需求:按住按钮,每200ms执行一次命令。

public class MainActivity8 extends AppCompatActivity {

    private static final String TAG = "MainActivity888";

    //长按时间阈值
    private static final long LONG_PRESS_TIMEOUT = 200L;
    //长按消息标识
    private static final int MSG_LONG_PRESS = 1;
    //线程池
    private ScheduledExecutorService delMsgExecutor = null;
    //线程安全类型Int
    private AtomicInteger mLongNumber = new AtomicInteger(0);
    //按下时间
    private long downTime = 0;
    //Handler
    private MyHandler mHandler = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main8);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onResume() {
        super.onResume();
        Button button1 = findViewById(R.id.button1);

        initHandler();

        button1.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downTime = System.currentTimeMillis();
                    sendLongPress();
                    break;
                case MotionEvent.ACTION_UP:
                    if ((System.currentTimeMillis() - downTime) < LONG_PRESS_TIMEOUT) {
                        Log.d(TAG, "短按操作");
                    }
                    downTime = 0L;
                    removeMessage();
                    break;
            }
            return false;
        });
    }

    /**
     * 初始化Handler
     */
    private void initHandler() {
        if (mHandler == null)
            mHandler = new MyHandler();
    }

    /**
     * 长按事件方法
     */
    private void sendLongPress() {
        //初始化线程池
        if (delMsgExecutor == null) {
            delMsgExecutor =
                    new ScheduledThreadPoolExecutor(1, r -> new Thread(r, "LongPressThread"));
        }

        //执行周期任务
        delMsgExecutor.scheduleWithFixedDelay(() -> {
            Message longPressMsg = mHandler.obtainMessage(MSG_LONG_PRESS, mLongNumber.addAndGet(1));
            mHandler.sendMessageDelayed(longPressMsg, LONG_PRESS_TIMEOUT);
        }, 1, LONG_PRESS_TIMEOUT, TimeUnit.MILLISECONDS);

        /*
            scheduleWithFixedDelay和scheduleFixedRate的区别:

            scheduleWithFixedDelay:
            从字面意义上可以理解为就是以固定延迟(时间)来执行线程任务,
            它实际上是不管线程任务的执行时间的,每次都要把任务执行完成后再延迟固定时间后再执行下一次。

            scheduleFixedRate:
            是以固定频率来执行线程任务,固定频率的含义就是可能设定的固定时间不足以完成线程任务,
            但是它不管,达到设定的延迟时间了就要执行下一次了。
         */
    }

    /**
     * 通知结束长按事件
     */
    private void removeMessage() {
        if (mHandler != null)
            mHandler.removeMessages(MSG_LONG_PRESS);
        mLongNumber.set(0);
        releaseExecutor();
    }

    /**
     * 释放线程池
     */
    private void releaseExecutor() {
        if (delMsgExecutor == null) return;

        delMsgExecutor.shutdown();
        delMsgExecutor = null;
    }

    private static class MyHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            if (msg.what == MSG_LONG_PRESS) {
                Log.d(TAG, "长按操作 >>  message obj: " + msg.obj);
            }
        }
    }
}

可封装成方法,通过接口回调直接使用。


import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.NonNull;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Author: MoMo
 * description:
 * Create: 2022/9/21
 */
public class MyLongTouchListener implements View.OnTouchListener {

    private static final String TAG = "MyLongTouchListener";

    //长按时间阈值
    private static final long LONG_PRESS_TIMEOUT = 200L;
    //长按消息标识
    private static final int MSG_LONG_PRESS = 1;
    //线程池
    private ScheduledExecutorService delMsgExecutor = null;
    //线程安全类型Int
    private AtomicInteger mLongNumber = new AtomicInteger(0);
    //按下时间
    private long downTime = 0;
    //Handler
    private MyHandler mHandler = null;

    //
    public interface OnLongTouchListener {
        void onClick();

        void onLongClick();
    }

    private OnLongTouchListener onLongTouchListener;


    public MyLongTouchListener(OnLongTouchListener onLongTouchListener) {
        this.onLongTouchListener = onLongTouchListener;
        initHandler(onLongTouchListener);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downTime = System.currentTimeMillis();
                sendLongPress();
                break;
            case MotionEvent.ACTION_UP:
                if ((System.currentTimeMillis() - downTime) < LONG_PRESS_TIMEOUT) {
                    //短按操作
                    if (onLongTouchListener != null)
                        onLongTouchListener.onClick();
                }
                downTime = 0L;
                removeMessage();
                break;
        }
        return false;
    }


    /**
     * 初始化Handler
     */
    private void initHandler(OnLongTouchListener onLongTouchListener) {
        if (mHandler == null)
            mHandler = new MyHandler(onLongTouchListener);
    }

    /**
     * 长按事件方法
     */
    private void sendLongPress() {
        //初始化线程池
        if (delMsgExecutor == null) {
            delMsgExecutor =
                    new ScheduledThreadPoolExecutor(1, r -> new Thread(r, "LongPressThread"));
        }

        //执行周期任务
        delMsgExecutor.scheduleWithFixedDelay(() -> {
            Message longPressMsg = mHandler.obtainMessage(MSG_LONG_PRESS, mLongNumber.addAndGet(1));
            mHandler.sendMessageDelayed(longPressMsg, LONG_PRESS_TIMEOUT);
        }, 1, LONG_PRESS_TIMEOUT, TimeUnit.MILLISECONDS);

        /*
            scheduleWithFixedDelay和scheduleFixedRate的区别:

            scheduleWithFixedDelay:
            从字面意义上可以理解为就是以固定延迟(时间)来执行线程任务,
            它实际上是不管线程任务的执行时间的,每次都要把任务执行完成后再延迟固定时间后再执行下一次。

            scheduleFixedRate:
            是以固定频率来执行线程任务,固定频率的含义就是可能设定的固定时间不足以完成线程任务,
            但是它不管,达到设定的延迟时间了就要执行下一次了。
         */
    }

    /**
     * 通知结束长按事件
     */
    private void removeMessage() {
        if (mHandler != null)
            mHandler.removeMessages(MSG_LONG_PRESS);
        mLongNumber.set(0);
        releaseExecutor();
    }

    /**
     * 释放线程池
     */
    private void releaseExecutor() {
        if (delMsgExecutor == null) return;

        delMsgExecutor.shutdown();
        delMsgExecutor = null;
    }

    private static class MyHandler extends Handler {
        private OnLongTouchListener onLongTouchListener;

        public MyHandler(OnLongTouchListener onLongTouchListener) {
            this.onLongTouchListener = onLongTouchListener;
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            if (msg.what == MSG_LONG_PRESS) {
                //长按操作
                if (onLongTouchListener != null)
                    onLongTouchListener.onLongClick();
            }
        }
    }
}

使用

button.setOnTouchListener(new MyLongTouchListener(new MyLongTouchListener.OnLongTouchListener() {
            @Override
            public void onClick() {
                Log.d(TAG, "短按回调");
            }

            @Override
            public void onLongClick() {
                Log.d(TAG, "长按回调");
            }
        }));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值