Reputation: 665
Is there a way in Xamarin Forms to customize the long press duration for Android and iOS? I believe the default duration is 1 second for each platform, but some of my users have been complaining that the long press events have been firing too quickly as they scroll through lists, etc. in my app. So I'd love to be able to bump that out to say 2 seconds on each platform. Any ideas?
Ideally I'd like to solve this issue by increasing the duration before a long press event is fired. If this isn't possible, is it possible to implement my own long press using a timer? I've seen a great example with a button using behaviors and the button's Pressed/Released events, but ideally I'd like this code to work for any control not just buttons and other controls don't have a Pressed/Released event.
Thank you!
Upvotes: 0
Views: 1748
Reputation: 1108
I've attached a Behavior to a button to get both long press and tap gestures
public class LongPressBehavior : Behavior<Button>
{
private static readonly object _syncObject = new object();
private Timer _timer;
private volatile bool _isReleased;
private object _context;
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(LongPressBehavior), default(ICommand));
public static readonly BindableProperty EarlyReleaseCommandProperty = BindableProperty.Create(nameof(EarlyReleaseCommand), typeof(ICommand), typeof(LongPressBehavior), default(ICommand));
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(LongPressBehavior));
public static readonly BindableProperty DurationProperty = BindableProperty.Create(nameof(Duration), typeof(int), typeof(LongPressBehavior), 1000);
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public ICommand EarlyReleaseCommand
{
get => (ICommand)GetValue(EarlyReleaseCommandProperty);
set => SetValue(EarlyReleaseCommandProperty, value);
}
public int Duration
{
get => (int)GetValue(DurationProperty);
set => SetValue(DurationProperty, value);
}
protected override void OnAttachedTo(ImageButton bindable)
{
base.OnAttachedTo(bindable);
bindable.Pressed += Button_Pressed;
bindable.Released += Button_Released;
}
protected override void OnDetachingFrom(ImageButton bindable)
{
base.OnDetachingFrom(bindable);
bindable.Pressed -= Button_Pressed;
bindable.Released -= Button_Released;
}
private void DeInitializeTimer()
{
lock (_syncObject)
{
if (_timer == null)
{
return;
}
_timer.Change(Timeout.Infinite, Timeout.Infinite);
_timer.Dispose();
_timer = null;
}
}
private void InitializeTimer()
{
lock (_syncObject)
{
_timer = new Timer(Timer_Elapsed, null, Duration, Timeout.Infinite);
}
}
private void Button_Pressed(object sender, EventArgs e)
{
_isReleased = false;
_context = (sender as ImageButton)?.BindingContext;
InitializeTimer();
}
private void Button_Released(object sender, EventArgs e)
{
if (!_isReleased)
{
EarlyReleaseCommand?.Execute(CommandParameter);
}
_isReleased = true;
_context = null;
DeInitializeTimer();
}
protected virtual void OnLongPressed()
{
if (Command != null && Command.CanExecute(CommandParameter))
{
if (CommandParameter == null && Command.CanExecute(_context))
{
Command.Execute(_context);
return;
}
Command.Execute(CommandParameter);
}
}
public LongPressBehavior()
{
_isReleased = true;
}
private void Timer_Elapsed(object state)
{
DeInitializeTimer();
if (_isReleased)
{
return;
}
_isReleased = true;
Device.BeginInvokeOnMainThread(OnLongPressed);
}
}
You can use it as:
<Button Text="Long Press Me!">
<Button.Behaviors>
<behaviors:LongPressBehavior Command="{Binding LongPressCommand}" EarlyReleaseCommand="{Binding TapCommand}" Duration="5000" />
</Button.Behaviors>
</Button>
Upvotes: 0
Reputation: 15796
In iOS, you can change the MinimumPressDuration
of UILongPressGestureRecognizer to achieve that.
It's the minimum time, in seconds, fingers must press for the gesture to be recognized. Default is 0.5.
Code is :
public iOSLongPressedEffect()
{
_longPressRecognizer = new UILongPressGestureRecognizer(HandleLongClick);
_longPressRecognizer.MinimumPressDuration = 5;
}
In Android, it seems you can't change the duration directly. You have to implement your own logic in the method OnTouchListener
to achieve that.
Have a look at these threads may help:
android-how-to-increase-long-press-time
how-can-i-increase-the-clicktime
BTW, in this issue in Github of Xamarin.forms, there says a LongPressGestureRecognizer
api would be added in the future.
Upvotes: 1