我通过子类化RoutingEffect
创建了自定义效果,以允许Xamarin项目中的LongPressGesture
和iOS
都使用Android
。
我正在共享项目的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
执行命令C0],有关如何解决此问题的任何想法?
注意:如果我使用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);
}
}
}
这是Xamarin中的错误,可以找到更多详细信息here
作为解决方法,我使用了图像按钮,我的XAML现在看起来像这样:
<ImageButton x:Name="TapRight" Grid.Row="4" Grid.Column="2" Source="right64"
IsEnabled="{Binding RightEnabled}"
Opacity="{Binding RightEnabled, Converter={StaticResource OpacityConverter}}"
effects:LongPressEffect.Command="{Binding LongPressGestureCommand}"
effects:LongPressEffect.CommandParameter="{x:Static common:NavType.Right}"
Command="{Binding TapGestureNavCommand}"
CommandParameter="{x:Static common:NavType.Right}">
<ImageButton.Effects>
<effects:LongPressEffect></effects:LongPressEffect>
</ImageButton.Effects>
</ImageButton>