为了实现对Android任意控件和按键进行双击事件的监听,因此写了一个能够在代码中任意移植的解决方法。android
1、解决思路bash
为了实现双击事件的监听,首先须要一个线程来执行两次点击事件的判断,决定是否属于一次双击事件,为了能够实现屡次监听,因此在线程中是一个死循环,避免开无数个线程;而后将判断结果经过handler传递出去,由handler对message中携带的boolean数据进行判断,决定回调双击事件监听器中的双击或单击方法,监听器中的事件由用户覆写;最后在本身想要添加双击事件监听的控件或按键的点击事件监听器中建立一个双加事件管理器并启动就能够了。ide
2、准备工做函数
1.建立双击事件监听器接口oop
/**
* Created by 明月春秋 on 2017/11/18.
* 负责对是否双击事件结果的回调监听器
* 方法:
* 1.onSinglePress:用于处理单击事件
* 2.onDoublePress:用于处理双击事件
*/
public interface OnDoubleClickListener {
/**
* 用于处理单击事件
*/
public void onSinglePress();
/**
* 用于处理双击事件
*/
public void onDoublePress();
}复制代码
2.建立双击事件处理handler,用来决定是执行监听器中的双击事件仍是单击事件布局
/**
* Created by 明月春秋 on 2017/11/18.
* 负责处理双击事件的handler
* 方法:
* 1.setDoubleRunnable:设置handler处理所在的线程执行体
*/
public class DoubleHandler extends Handler {
private OnDoubleClickListener mListener;//对是否双击结果的回调监听器
private DoubleRunnable mDoubleRunnable;//负责双击事件的线程执行体
/**
* 双击事件处理器的构造函数
* @param listener
* 对是否双击结果的回调监听器
*/
public DoubleHandler(OnDoubleClickListener listener){
super(Looper.getMainLooper());
this.mListener = listener;
}
@Override
public void handleMessage(Message msg) {
if ((boolean)msg.obj){
mListener.onDoublePress();
}
else {
mListener.onSinglePress();
}
//通知双击事件线程执行体,事件已处理完
mDoubleRunnable.setIsStarted(false);
}
/**
* 设置handler处理所在的线程执行体
* @param doubleRunnable
* 传入的当前线程执行体
*/
public void setDoubleRunnable(DoubleRunnable doubleRunnable){
this.mDoubleRunnable = doubleRunnable;
}
}复制代码
3.建立执行双击事件判断的线程执行体,在其中进行死循环,一直等待用户的点击,并对相关运行状态进行判断,将双击事件的判断结果发送给前面的DoubleHandler 进行处理ui
/**
* Created by 明月春秋 on 2017/11/18.
* 负责双击事件的线程执行体
* 方法:
* 1.setPreparedState:设置当前双击事件的执行状态
* 2.setIsStarted:设置线程是否处于一次双击事件判断的阻塞之中
* 3.setDoubleSpan:设置用于判断双击的间隔时间
*/
public class DoubleRunnable implements Runnable {
private DoubleHandler mHandler;//处理点击事件的handler
private boolean isStarted = false;//表示线程是否正处于阻塞中
private boolean isPrepared = false;//表示是否已准备好启动线程
private boolean isDoubleClicked = false;//表示是否被双击
private int doubleSpan;//用于判断双击的间隔时间
/**
* 双击事件线程执行体的构造函数
* @param handler
* 用于处理是否双击事件的handler
*/
public DoubleRunnable(DoubleHandler handler) {
handler.setDoubleRunnable(this);
this.mHandler = handler;
}
@Override
public void run() {
while (true){
//若是没有被点击,则继续下次循环
if (!isPrepared) {
continue;
}
isPrepared = false;
//若是线程处于一次双击事件的阻塞中,则继续下次循环,直至事件结束
if (isStarted){
continue;
}
isStarted = true;
try {
Thread.sleep(doubleSpan);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = mHandler.obtainMessage();
msg.obj = isDoubleClicked;
mHandler.sendMessage(msg);
}
}
/**
* 设置当前双击事件的执行状态
* @param isPrepared
* 是否已被点击(能够执行线程中代码)
* @param isDoubleClicked
* 是否已被双击
*/
public void setPreparedState(boolean isPrepared, boolean isDoubleClicked) {
this.isPrepared = isPrepared;
this.isDoubleClicked = isDoubleClicked;
}
/**
* 设置线程是否处于一次双击事件判断的阻塞之中
* @param isStarted
* 传入是否阻塞开启
*/
public void setIsStarted(boolean isStarted){
this.isStarted = isStarted;
}
/**
* 设置用于判断双击的间隔时间
* @param doubleSpan
* 传入的时间间隔
*/
public void setDoubleSpan(int doubleSpan){
this.doubleSpan = doubleSpan;
}
}复制代码
4.最后建立一个双击事件管理器,进行线程的建立管理,并用于启动线程和更新用户的点击时间,之因此在管理器中更新时间并进行判断,是由于能够随时根据用户的点击去更新DoubleRunnable中的双击判断结果,若是在DoubleRunnable中进行时间判断,则会由于判断只会在下一次阻塞循环结束以后才能进行,致使一直是单击事件执行。this
/**
* Created by 明月春秋 on 2017/11/18.
* 双击事件的管理器
* 方法:
* 1.start:开启双击事件的线程执行
*/
public class DoubleManager {
private DoubleRunnable mDoubleRunnable = null;//负责双击事件的线程执行体
private Thread mThread = null;//负责双击事件的线程
private long mClickTime = 0;//记录点击时间
private static final int DOUBLE_SPAN = 300;//用于判断双击的间隔时间
/**
* 双击事件管理器的构造函数
* @param doubleRunnable
* 传入负责双击事件的线程执行体
*/
public DoubleManager(DoubleRunnable doubleRunnable){
if (doubleRunnable == null){
return;
}
if (mDoubleRunnable == null){
doubleRunnable.setDoubleSpan(DOUBLE_SPAN);
this.mDoubleRunnable = doubleRunnable;
}
}
/**
* 开启双击事件的线程执行
*/
public void start(){
if (mDoubleRunnable == null){
return;
}
boolean isDoubleClicked = false;
if ((System.currentTimeMillis() - mClickTime) < DOUBLE_SPAN) {
isDoubleClicked = true;
}
else {
isDoubleClicked = false;
mClickTime = System.currentTimeMillis();
}
mDoubleRunnable.setPreparedState(true, isDoubleClicked);
if (mThread == null){
mThread = new Thread(mDoubleRunnable);
mThread.start();
}
}
}复制代码
5.接下来就能够在任意控件的单击事件监听器中或按键事件中,进行双击事件的判断了。spa
public class DoubleClick extends AppCompatActivity {
private DoubleManager doubleManager = null;
private DoubleManager keyDoubleManager = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.button_double_click);
}
public void doubleClick(View view){
if (doubleManager == null){
doubleManager = new DoubleManager(new DoubleRunnable(new DoubleHandler(new OnDoubleClickListener() {
@Override
public void onSinglePress() {
Toast.makeText(DoubleClick.this, "单击", Toast.LENGTH_SHORT).show();
}
@Override
public void onDoublePress() {
Toast.makeText(DoubleClick.this, "双击", Toast.LENGTH_SHORT).show();
}
})));
}
doubleManager.start();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER){
if (keyDoubleManager == null){
keyDoubleManager = new DoubleManager(new DoubleRunnable(new DoubleHandler(new OnDoubleClickListener() {
@Override
public void onSinglePress() {
Toast.makeText(DoubleClick.this, "按键单击", Toast.LENGTH_SHORT).show();
}
@Override
public void onDoublePress() {
Toast.makeText(DoubleClick.this, "按键双击", Toast.LENGTH_SHORT).show();
}
})));
}
keyDoubleManager.start();
}
return super.onKeyDown(keyCode, event);
}
}复制代码
运行例子中按键事件时,记得将Button在布局中设为android:visibility="gone",防止按键事件直接点击到按钮上,执行按钮的双击事件监听了。线程
3、运行效果图
1.执行按钮单击
2.执行按钮双击
3.执行按键单击
4.执行按键双击
4、总结到此,Android任意控件或按键的双击事件监听就已经所有实现了。只要前面将准备工做作好,就能够随意在任何代码处添加双击事件管理器并执行了,不会对原有代码产生任何影响,若是对本文有什么意见和问题欢迎指正,若是以为本文能够,请帮忙点个赞,谢谢观看。