在使用App
的时候,经常会出现这种情况,比如快速点击的时候打开了两个一模一样的页面,或者弹出多个弹出框,或者快速点击的时候,提交了两次数据(一般情况下还会加Loading
,然后加上设置控件的enable
来实现)。这个时候就需要做一些处理来防止快速点击。
我看了网上的一些做法,我认为是比较麻烦或者不可取的。比如,
- 为
Activity
设置启动模式为singleTop
- 定义一个变量来记录上一次点击时间,然后根据这个变量来判断是否可以点击。
第一种方法比较侵入,因为有的页面有自己的启动模式,而且该方法只能用在打开页面的这种情况,并不能本质解决防止快速点击的问题
第二种方法可以实现,但是比较麻烦,因为这样的话,如果一个页面有很多控件的话,就会出现很多的变量。
我这里对第二种方法进行改进,使其可以针对单控件或者多控件,在使用时也与OnClickListener
基本无异,使用了抽象代替了接口而已。(如果非要在Activivty
等界面实现OnClickListener
的话,可以使用动态代理的方法进行实现,代码都不变,需要设置监听的时候由原OnClickListener实例
变更为OnClickListener代理
)
import android.util.Log;
import android.util.SparseLongArray;
import android.view.View;
/**
* Created by ivy on 2017/4/5.
* Description:
*/
public abstract class PreventRepeatOnClickListener implements View.OnClickListener{
private SparseLongArray mLastClickTimeRecordArray=new SparseLongArray();
private long mClickInterVal=300;
//是阻止一个控件快速点击(比如快速点击A),还是所有设置了该监听的控件都不能快速点击(比如不能同时点击A,B控件,包括快速点击A)
private boolean isPreventRepeatOnClickOneView=true;
private long mLastClickTime=0;
public void setClickInterVal(long clickInterVal){
this.mClickInterVal=clickInterVal;
}
public void setPreventRepeatOnClickOneView(boolean isPreventRepeatOnClickOneView){
this.isPreventRepeatOnClickOneView=isPreventRepeatOnClickOneView;
}
@Override
public void onClick(View v) {
if (v.getId()!=0){
if (isPreventRepeatOnClickOneView) {
preventOneViewRepeatClick(v);
}else{
preventAllViewRepeatClick(v);
}
}else{
Log.e(this.getClass().getName(),"this view("+v.toString()+") not set id, so we can't prevent repeat click!!");
}
}
private void preventAllViewRepeatClick(View v) {
long currentClickTime = System.currentTimeMillis();
if (currentClickTime-mLastClickTime>=mClickInterVal){
mLastClickTime=currentClickTime;
mLastClickTimeRecordArray.put(v.getId(),currentClickTime);
onClickView(v);
}
}
private void preventOneViewRepeatClick(View v) {
long lastClickTime = mLastClickTimeRecordArray.get(v.getId());
long currentClickTime = System.currentTimeMillis();
if (currentClickTime - lastClickTime >= mClickInterVal) {
mLastClickTime=currentClickTime;
mLastClickTimeRecordArray.put(v.getId(), currentClickTime);
onClickView(v);
}
}
abstract void onClickView(View v);
}
通过继承OnClickListener()
,然后在点击的时候通过SparseLongArray
和控件id
来记录上一次点击的时间戳,然后再次点击的时候根据当前时间戳和上一次点击的时间戳进行比较,看是否小于最小点击时间,如果是的话则不执行点击回调,否则的话执行点击。这样的话便可以简单的防止快速点击。使用的时候只需要简单的new
一个PreventRepeatOnClickListener
实例,然后为需要该特性的控件设置该监听,即可以实现防止快速点击同一控件的问题。