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?
– Geison Santos
You’d need to change the
Button
in xml bynome.do.seu.pacote.SingleClickButton
, to use this subclass.– Wakim