Xamarin.Android Tap手势和长按手势无法同时使用

时间:2019-11-04 17:06:20

标签: c# android xamarin xamarin.forms xamarin.android

我通过子类化RoutingEffect来创建自定义效果,以便在我的Xamarin项目中同时允许LongPressGestureiOS都使用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的命令,有关如何解决此问题的任何想法?

注意::如果我使用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);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这是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>