Avoid button multiple rapid clicks

前端 未结 20 1471
猫巷女王i
猫巷女王i 2020-11-28 02:55

I have a problem with my app that if the user clicks the button multiple times quickly, then multiple events are generated before even my dialog holding the button disappear

相关标签:
20条回答
  • 2020-11-28 03:22

    Here's my version of the accepted answer. It is very similar, but doesn't try to store Views in a Map which I don't think is such a good idea. It also adds a wrap method that could be useful in many situations.

    /**
     * Implementation of {@link OnClickListener} that ignores subsequent clicks that happen too quickly after the first one.<br/>
     * To use this class, implement {@link #onSingleClick(View)} instead of {@link OnClickListener#onClick(View)}.
     */
    public abstract class OnSingleClickListener implements OnClickListener {
        private static final String TAG = OnSingleClickListener.class.getSimpleName();
    
        private static final long MIN_DELAY_MS = 500;
    
        private long mLastClickTime;
    
        @Override
        public final void onClick(View v) {
            long lastClickTime = mLastClickTime;
            long now = System.currentTimeMillis();
            mLastClickTime = now;
            if (now - lastClickTime < MIN_DELAY_MS) {
                // Too fast: ignore
                if (Config.LOGD) Log.d(TAG, "onClick Clicked too quickly: ignored");
            } else {
                // Register the click
                onSingleClick(v);
            }
        }
    
        /**
         * Called when a view has been clicked.
         * 
         * @param v The view that was clicked.
         */
        public abstract void onSingleClick(View v);
    
        /**
         * Wraps an {@link OnClickListener} into an {@link OnSingleClickListener}.<br/>
         * The argument's {@link OnClickListener#onClick(View)} method will be called when a single click is registered.
         * 
         * @param onClickListener The listener to wrap.
         * @return the wrapped listener.
         */
        public static OnClickListener wrap(final OnClickListener onClickListener) {
            return new OnSingleClickListener() {
                @Override
                public void onSingleClick(View v) {
                    onClickListener.onClick(v);
                }
            };
        }
    }
    
    0 讨论(0)
  • 2020-11-28 03:22

    More significant way to handle this scenario is using Throttling operator (Throttle First) with RxJava2. Steps to achieve this in Kotlin :

    1). Dependencies :- Add rxjava2 dependency in build.gradle app level file.

    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
    

    2). Construct an abstract class that implements View.OnClickListener & contains throttle first operator to handle the view’s OnClick() method. Code snippet is as:

    import android.util.Log
    import android.view.View
    import io.reactivex.android.schedulers.AndroidSchedulers
    import io.reactivex.subjects.PublishSubject
    import java.util.concurrent.TimeUnit
    
    abstract class SingleClickListener : View.OnClickListener {
       private val publishSubject: PublishSubject<View> = PublishSubject.create()
       private val THRESHOLD_MILLIS: Long = 600L
    
       abstract fun onClicked(v: View)
    
       override fun onClick(p0: View?) {
           if (p0 != null) {
               Log.d("Tag", "Clicked occurred")
               publishSubject.onNext(p0)
           }
       }
    
       init {
           publishSubject.throttleFirst(THRESHOLD_MILLIS, TimeUnit.MILLISECONDS)
                   .observeOn(AndroidSchedulers.mainThread())
                   .subscribe { v -> onClicked(v) }
       }
    }
    

    3). Implement this SingleClickListener class on the click of view in activity. This can be achieved as :

    override fun onCreate(savedInstanceState: Bundle?)  {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)
    
       val singleClickListener = object : SingleClickListener(){
          override fun onClicked(v: View) {
           // operation on click of xm_view_id
          }
      }
    xm_viewl_id.setOnClickListener(singleClickListener)
    }
    

    Implementing these above steps into the app can simply avoid the multiple clicks on a view till 600mS. Happy coding!

    0 讨论(0)
提交回复
热议问题