Search code examples
androidbutterknife

Button Click triggered multiple times


A common problem in android apps for me seems to be, that click events can be triggered multiple times, when they should not.

I am using Butterknife - consider the following example

@OnClick(R.id.button_foto_aufnehmen)
protected void takePicture() {
  m_camera.takePicture();
}

with a camera app with some layout containing

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    ...

    <ImageButton
        android:id="@+id/button_foto_aufnehmen"
        .../>

Now it should not be possible to click the button again, until at least after the onPictureTaken callback has completed - or even later.

Another example would be

I really don't want to manually introduce a boolean flag every time this comes up. I'd think of something like an annotation that allows me to specify an event that resets a boolean which is generated automatically. Anything but boilerplate code please.

So what is the best practice here (particularly keeping in mind the usage of butter knife)?


Solution

  • I have faced this situation before. Basically I ended up implementing my own CustomClickListener and setting a threshold of a specific time interval (for instance, 1000ms) before allowing firing the trigger. Basically when you click the button and trigger the listener, it will check if the trigger was executed in the past amount of time you defined, and if not it will trigger it.

    public class CustomClickListener implements View.OnClickListener {
    
        protected int defaultInterval;
        private long lastTimeClicked = 0;
    
        public CustomClickListener() {
            this(1000);
        }
    
        public CustomClickListener(int minInterval) {
            this.defaultInterval = minInterval;
        }
    
        @Override
        public void onClick(View v) {
            if (SystemClock.elapsedRealtime() - lastTimeClicked < defaultInterval) {
                return;
            }
            lastTimeClicked = SystemClock.elapsedRealtime();
            performClick(v);
        }
    
         public abstract void performClick(View v);
    
    }
    

    And in your class, you can do the following without jeopardizing your implementation (normal code)

    myButton = (Button) findViewById(R.id.my_button);
    myButton.setOnClickListener(new CustomClickListener() {
        @Override
        public void performClick(View view) {
            // do stuff
        }
    });
    

    or by using a ButterKnife implentation (I have not tested yet since I dont have Android Studio available within my grasp at the moment, so if it works let me know) :

    @Bind(R.id.my_button)
    Button myButton;
    
    @OnClick(R.id.button)
    @Override
    public void performClick(View view) {
         // do stuff
    }
    

    Regards,