'Disable Android double tap on Xamarin Forms Label
Hey so I'm working Xamarin Forms and I'm dealing with the issue of android double tap.
My problem is that I'm using a label as button - and when I click this rapidly, the app will crash. I want to prevent this by disabling tapping after this is clicked.
My Label is defined in the XAML like this:
<Label x:Name="LabelName" Text="LabelText"/>
And my code-behind is like this:
LabelName.GestureRecognizers.Add((new TapGestureRecognizer
{
Command = new Command(async o =>
{
await Navigation.PopToRootAsync();
})
}));
Solution 1:[1]
Well, you can have an external boolean to avoid that (also, not sure but disabling temporarily the Label may work):
//On the form, so you can use a reference to This, else this is a value variable and will be copied and false always
bool disable = false;
And then:
LabelName.GestureRecognizers.Add((new TapGestureRecognizer
{
Command = new Command(async o =>
{
if(this.disable)
return;
this.disable = true;
await Navigation.PopToRootAsync();
this.disable = false;
})
}));
Solution 2:[2]
On Android, the UI registers multiple taps and queues them up to execute one after the other. So double tapping on a button can execute the command twice and cause unintended behavior. The simplest way is to have your commands observe a bool property and toggle that property on/off. Something like this,
SomeCommand = new Command (OnCommand,(x)=> CanNavigate);
async void OnCommand (object obj)
{
CanNavigate = false;
await CurrentPage.DisplayAlert ("Hello", "From intelliAbb", "OK");
CanNavigate = true;
}
You can checkout the complete example at https://intelliabb.com/2017/02/18/handling-multiple-taps-in-xamarin-forms-on-android/
Solution 3:[3]
The simplest method is to disable the element that's triggering the tap event.
You can achieve this by following the example below:
var tapRecognizer = new TapGestureRecognizer();
tapRecognizer.Tapped += async (s,e) =>
{
((View)s).IsEnabled = false; // or reference the view directly if you have access to it
await Navigation.PopToRootAsync();
((View)s).IsEnabled = true;
};
theLabel.GestureRecognizers.Add(tapRecognizer);
Solution 4:[4]
You need to make an Action that will disable your view. You can add configurable timeout to disable it. You can implement it for click or Views and add any other methods you like to control the press. Your code should look like this:
public abstract class ThrottlingListener : Java.Lang.Object
{
readonly TimeSpan timeout;
protected ThrottlingListener( TimeSpan timeout = default(TimeSpan))
{
this.timeout = timeout == TimeSpan.Zero ? TimeSpan.FromSeconds(1) : timeout;
}
protected bool IsThrottling()
{
var now = DateTime.UtcNow;
if (now - LastClick < timeout)
{
return true;
}
LastClick = now;
return false;
}
protected DateTime LastClick{ get; private set;}
protected void DisableView(View view)
{
view.Enabled = false;
view.PostDelayed (() =>
{
view.Enabled = true;
}, (long)timeout.TotalMilliseconds);
}
}
public class ThrottlingOnClickListener : ThrottlingListener, View.IOnClickListener
{
readonly Action onClick;
public ThrottlingOnClickListener(Action onClick, TimeSpan timeout = default(TimeSpan)) : base(timeout)
{
this.onClick = onClick;
}
public void OnClick(View view)
{
if (IsThrottling())
return;
DisableView (view);
onClick ();
}
}
Solution 5:[5]
Here's what I do in C#:
private static object _tappedLockObject = new object();
private static bool _tapped = false;
private void tapHandler()
{
// one-at-a-time access to this block prevents duplicate concurrent requests:
lock(_tappedLockObject)
{
if(_tapped) return;
_tapped = true;
}
handleTap();
}
private void reenableTap()
{
_tapped = false;
}
With this solution, you'll still get multiple tap noises. But that's a different question, right?
Solution 6:[6]
Just check if the application is Busy when click the button
if (IsBusy)
return;
Solution 7:[7]
Using AsyncCommand with allowsMultipleExecutions: false helped in my case:
public ICommand TappedCommand => _tappedCommand ?? (_tappedCommand =
new AsyncCommand(() => Navigation.PopAsync(), allowsMultipleExecutions: false));
Solution 8:[8]
I solved it, this is the solution:
class Resistor(QGraphicsPathItem):
def __init__(self, x, y):
super(Resistor, self).__init__()
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.setAcceptHoverEvents(True)
self.isSelected = False
self.setPath(self.create_path())
self.setPos(x, y)
def create_path(self):
path = QPainterPath()
path.moveTo(0, 33)
path.lineTo(0, 18)
path.lineTo(12, 15)
path.lineTo(-12, 9)
path.lineTo(12, 3)
path.lineTo(-12, -3)
path.lineTo(12, -9)
path.lineTo(-12, -15)
path.lineTo(0, -18)
path.lineTo(0, -33)
return path
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Gusman |
| Solution 2 | hnabbasi |
| Solution 3 | chaosifier |
| Solution 4 | user3030630 |
| Solution 5 | tele-bird |
| Solution 6 | Mahmoud Abdeen |
| Solution 7 | maf-soft |
| Solution 8 | Dani RedRain |
