Prevent multiple clicks on Android

Asked

Viewed 141 times

2

I have a user registration screen where I avoid the possibility of multiple clicks to the sign up button through the method View.setEnabled(). Proceed as follows: in the method onClick(), from the View.Onclicklistener interface, I disable the button and, after the request has ended, in the method onPostExecute() of Asynctask the able again.

Although it is a simple solution, I read in ONLY AMERICAN that this solution does not adequately solve the problem. In the answer given in this thread the author cites the fact that clicks are queued to be executed later.

Faced with the fact highlighted I ask: the solution adopted in the American OS is the final solution to solve the problem or there is a better or ideal solution to solve it?

1 answer

1


Yes, this problem occurs because it postpones click detection using the post and postDelayed, and this will line up the events of ACTION_UP. This can be seen by the source code of the class View:

// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
if (mPerformClick == null) {
    mPerformClick = new PerformClick();
}

if (!post(mPerformClick)) {
    performClick();
}

I can’t think of a better way to do it, the flag is enough.

But I think we can improve this a little, making this logic centralized in a subclass of Button. So you avoid code replication, and make it transparent to those who use it. You would still need to set the setEnabled because of asynchronous processing, otherwise just do the flag management enabled before and after the call from performClick of the father (super).

My suggestion would be:

public class SingleClickButton extends Button {
    public SingleClickButton(Context context) {
        super(context);
    }

    public SingleClickButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SingleClickButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SingleClickButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean performClick() {
        return isEnabled() && super.performClick();
    }
}

This solution will still queue events, but will not let them run repeatedly. To avoid the accumulation of events, there would have to be the overwriting of the onTouchEvent, but it’s a more aggressive approach and I think it’s unnecessary.

To use in a layout of yours, simply declare the tag with the entire path of the package and class:

<nome.do.seu.pacote.SingleClickButton
    ...
/>
  • Hello, Walkin. How can I make use of this solution presented by you? How to make the button of my view make use of this subclass?

  • You’d need to change the Button in xml by nome.do.seu.pacote.SingleClickButton, to use this subclass.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.