Я создал пользовательский эффект, создав подкласс RoutingEffect
, чтобы разрешить LongPressGesture
для iOS
и Android
в моем проекте Xamarin.
Я использую этот эффект на Image
в XAML
моего общего проекта, и этот же Image
также использует TapGesture
, см. код ниже:
<Image x:Name="TapRight" Grid.Row="4" Grid.Column="2" Source="right64"
VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
IsEnabled="{Binding RightEnabled}"
Opacity="{Binding RightEnabled, Converter={StaticResource OpacityConverter}}"
effects:LongPressEffect.Command="{Binding LongPressGestureCommand}"
effects:LongPressEffect.CommandParameter="{x:Static common:NavType.Right}">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapGestureNavCommand}"
NumberOfTapsRequired="1"
CommandParameter="{x:Static common:NavType.Right}"/>
</Image.GestureRecognizers>
<Image.Effects>
<effects:LongPressEffect></effects:LongPressEffect>
</Image.Effects>
</Image>
Это прекрасно работает для iOS
(я получаю отдельнофункциональность, когда я нажимаю vs, когда я долго нажимаю на изображение), однако для Android
, это позволяет мне только делать длительное нажатие, и не выполняет команду для TapGesture
, есть идеи, как это исправить?
ПРИМЕЧАНИЕ: Если я использую Button
вместо Image
, он работает нормально. Тем не менее, я действительно хотел бы использовать Image
.
Я добавил еще код для справки:
Код для эффекта в общем проекте:
using System.Windows.Input;
using Xamarin.Forms;
namespace MyApp.Effects
{
public class LongPressEffect : RoutingEffect
{
public LongPressEffect() : base("Xamarin.LongPressEffect")
{
}
public static readonly BindableProperty CommandProperty =
BindableProperty.CreateAttached("Command",
typeof(ICommand),
typeof(LongPressEffect),
(object)null,
propertyChanged: OnCommandChanged);
public static ICommand GetCommand(BindableObject view)
{
return (ICommand)view.GetValue(CommandProperty);
}
public static void SetCommand(BindableObject view, ICommand value)
{
view.SetValue(CommandProperty, value);
}
static void OnCommandChanged(BindableObject bindable, object oldValue, object newValue)
{
var view = bindable as View;
if (view == null)
{
return;
}
ICommand command = (ICommand)newValue;
if (command != null)
{
view.SetValue(CommandProperty, command);
}
}
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.CreateAttached("CommandParameter",
typeof(object),
typeof(LongPressEffect),
(object)null,
propertyChanged: OnCommandParameterChanged);
public static object GetCommandParameter(BindableObject view)
{
return (object)view.GetValue(CommandParameterProperty);
}
public static void SetCommandParameter(BindableObject view, object value)
{
view.SetValue(CommandParameterProperty, value);
}
static void OnCommandParameterChanged(BindableObject bindable, object oldValue, object newValue)
{
var view = bindable as View;
if (view == null)
{
return;
}
object commandParameter = (object)newValue;
if (commandParameter != null)
{
view.SetValue(CommandParameterProperty, commandParameter);
}
}
}
}
Код для эффекта в iOS:
using System;
using System.ComponentModel;
using MyApp.Effects;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("Xamarin")]
[assembly:ExportEffect (typeof(MyApp.iOS.Effects.LongPressEffect), "LongPressEffect")]
namespace MyApp.iOS.Effects
{
public class LongPressEffect : PlatformEffect
{
private readonly UILongPressGestureRecognizer _longPressGestureRecognizer;
private bool _attached;
public LongPressEffect()
{
_longPressGestureRecognizer = new UILongPressGestureRecognizer(HandleLongClick);
_attached = false;
}
protected override void OnAttached()
{
if (!_attached)
{
Container.AddGestureRecognizer(_longPressGestureRecognizer);
_attached = true;
}
}
private void HandleLongClick()
{
if (_longPressGestureRecognizer.State == UIGestureRecognizerState.Ended)
// Only execute when the press is ended.
{
var command = MyApp.Effects.LongPressEffect.GetCommand(Element);
command?.Execute(MyApp.Effects.LongPressEffect.GetCommandParameter(Element));
}
}
protected override void OnDetached()
{
if (_attached)
{
Container.RemoveGestureRecognizer(_longPressGestureRecognizer);
_attached = false;
}
}
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
}
}
}
Код для эффекта в Android:
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(MyApp.Droid.Effects.LongPressEffect), "LongPressEffect")]
namespace MyApp.Droid.Effects
{
public class LongPressEffect: PlatformEffect
{
private bool _attached;
public static void Initialize() { }
public LongPressEffect()
{
_attached = false;
}
protected override void OnAttached()
{
Console.WriteLine("Invoking long click command...");
//throw new NotImplementedException();
if (!_attached) {
if (Control != null)
{
Control.LongClickable = true;
Control.LongClick += HandleLongClick;
}
_attached = true;
}
}
private void HandleLongClick(object sender, Android.Views.View.LongClickEventArgs e) {
Console.WriteLine("Invoking long click command...");
var command = MyApp.Effects.LongPressEffect.GetCommand(Element);
command?.Execute(MyApp.Effects.LongPressEffect.GetCommandParameter(Element));
}
protected override void OnDetached()
{
//throw new NotImplementedException();
if (_attached) {
if (Control != null) {
Control.LongClickable = true;
Control.LongClick -= HandleLongClick;
}
_attached = false;
}
}
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
}
}
}