如何在Xamarin Forms中制作长按手势?

Jos*_*man 8 gesture xamarin xamarin.forms

能告诉我如何识别Xamarin Forms应用程序中的长按手势?

我用前几天 TapGestureRecognizer

TapGestureRecognizer imageTap = new TapGestureRecognizer();
imageTap.Tapped += (sender, args) => this.OnClickImage;
image.GestureRecognizers.Add(imageTap);
Run Code Online (Sandbox Code Playgroud)

但我不知道如何根据xamarin论坛的这个帖子做长按手势

它应该看起来像这样,但它不起作用.

var dumpParam = new RelayGesture((g, x) => DisplayAlert("Title", "Hello message", "Cancel"));

book.Cover.SetValue(Gestures.InterestsProperty, new GestureCollection() {
    new GestureInterest
        {
            GestureType = GestureType.LongPress
            GestureCommand = // what should I set?
            GestureParameter = dumpParam
        }
 });
Run Code Online (Sandbox Code Playgroud)

如何设置我的自定义处理程序方法?

zaf*_*far 8

您可以通过附加以下行为来跨平台执行该操作,只要它是行为Xamarin.Forms.Button或其子类型即可。

using System;
using System.Threading;
using System.Windows.Input;
using Xamarin.Forms;

namespace App.Controls.Behaviors
{
    public class LongPressBehavior : Behavior<Button>
    {
        private readonly object _syncObject = new object();
        private const int Duration = 1000;

        //timer to track long press
        private Timer _timer;
        //the timeout value for long press
        private readonly int _duration;
        //whether the button was released after press
        private volatile bool _isReleased;

        /// <summary>
        /// Occurs when the associated button is long pressed.
        /// </summary>
        public event EventHandler LongPressed;

        public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command),
            typeof(ICommand), typeof(LongPressBehavior), default(ICommand));

        public static readonly BindableProperty CommandParameterProperty =
            BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(LongPressBehavior));

        /// <summary>
        /// Gets or sets the command parameter.
        /// </summary>
        public object CommandParameter
        {
            get => GetValue(CommandParameterProperty);
            set => SetValue(CommandParameterProperty, value);
        }

        /// <summary>
        /// Gets or sets the command.
        /// </summary>
        public ICommand Command
        {
            get => (ICommand)GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }

        protected override void OnAttachedTo(Button button)
        {
            base.OnAttachedTo(button);
            this.BindingContext = button.BindingContext;
            button.Pressed += Button_Pressed;
            button.Released += Button_Released;
        }

        protected override void OnDetachingFrom(Button button)
        {
            base.OnDetachingFrom(button);
            this.BindingContext = null;
            button.Pressed -= Button_Pressed;
            button.Released -= Button_Released;
        }

        /// <summary>
        /// DeInitializes and disposes the timer.
        /// </summary>
        private void DeInitializeTimer()
        {
            lock (_syncObject)
            {
                if (_timer == null)
                {
                    return;
                }
                _timer.Change(Timeout.Infinite, Timeout.Infinite);
                _timer.Dispose();
                _timer = null;
                Debug.WriteLine("Timer disposed...");
            }
        }

        /// <summary>
        /// Initializes the timer.
        /// </summary>
        private void InitializeTimer()
        {
            lock (_syncObject)
            {
                _timer = new Timer(Timer_Elapsed, null, _duration, Timeout.Infinite);
            }
        }

        private void Button_Pressed(object sender, EventArgs e)
        {
            _isReleased = false;
            InitializeTimer();
        }

        private void Button_Released(object sender, EventArgs e)
        {
            _isReleased = true;
            DeInitializeTimer();
        }

        protected virtual void OnLongPressed()
        {
            var handler = LongPressed;
            handler?.Invoke(this, EventArgs.Empty);
            if (Command != null && Command.CanExecute(CommandParameter))
            {
                Command.Execute(CommandParameter);
            }
        }

        public LongPressBehavior()
        {
            _isReleased = true;
            _duration = Duration;
        }

        public LongPressBehavior(int duration) : this()
        {
            _duration = duration;
        }

        private void Timer_Elapsed(object state)
        {
            DeInitializeTimer();
            if (_isReleased)
            {
                return;
            }
            Device.BeginInvokeOnMainThread(OnLongPressed);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在XAML用户界面中:

 <Button x:Name="MyButton" Text="Long Press Me!">
   <Button.Behaviors>
     <behaviors:LongPressBehavior LongPressed="MyButton_LongPressed"/>
   </Button.Behaviors>
 </Button>
Run Code Online (Sandbox Code Playgroud)

具有命令绑定的XAML UI:

 <Button x:Name="MyButton" Text="Long Press Me!">
   <Button.Behaviors>
     <behaviors:LongPressBehavior Command="{Binding CommandInViewModel}"/>
   </Button.Behaviors>
 </Button>
Run Code Online (Sandbox Code Playgroud)

  • 这不仅解决了我的问题,还教会了我如何在 Xamarin 中做一些我什至不知道是可能的事情。这比我回答的问题更多。 (2认同)
  • 我建议在这里稍作修改。您应该在“OnAttached()”中分配“OnBindingContextChanged”事件处理程序来处理绑定上下文问题。还要记住在“OnDetached()”中将其删除以进行清理。我将尝试编辑答案以反映这一点。但像这样:` private void OnBindingContextChanged(object sender, EventArgs e) { var button = sender as Button; BindingContext = 按钮?.BindingContext; }` 并在 OnAttached() 中添加 `button.BindingContextChanged += OnBindingContextChanged;` 并在 OnDetached 中使用 -= 删除 (2认同)

shu*_*wal 6

利用 XLabs.Forms nuget 包,它仅在 PCL 代码中制作长按和其他手势。使用 XLabs.Forms 包将减少在各个平台中自定义呈现的需要......在 .xaml 文件中添加 XAML 代码并在 .xaml.cs 文件中添加附加事件处理程序......它在 Android 中工作正常......

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="MultiImage.Page1"             
         xmlns:lc="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
         xmlns:lb="clr-namespace:XLabs.Forms.Behaviors;assembly=XLabs.Forms">
<ContentPage.Content>
    <lc:GesturesContentView ExcludeChildren="False" GestureRecognized="GesturesContentView_GestureRecognized">
         <lb:Gestures.Interests>
                <lb:GestureCollection>
                    <lb:GestureInterest GestureType="SingleTap"/>
                    <lb:GestureInterest GestureType="LongPress"/>
                    <lb:GestureInterest GestureType="DoubleTap"/>
                </lb:GestureCollection>
          </lb:Gestures.Interests>
          <Image Source="Myimage.png" Aspect="AspectFit" HeightRequest="100"/>
        </lc:GesturesContentView>
</ContentPage.Content>
Run Code Online (Sandbox Code Playgroud)

C#后端代码:

private void GesturesContentView_GestureRecognized(object sender, GestureResult e)
{           
    switch (e.GestureType)
    {
        case GestureType.LongPress:
            //Add code here
            break;
        case GestureType.SingleTap:
            // Add code here                    
            break;
        case GestureType.DoubleTap:
            // Add code here
            break;
        default:
            break;
    }
Run Code Online (Sandbox Code Playgroud)


Ric*_*rby 5

我最近遇到了这个问题,并找到了关于该主题的有用帖子https://alexdunn.org/2017/12/27/xamarin-tip-xamarin-forms-long-press-effect/

这将使用RoutingEffect并通过一个示例来说明如何创建 iOS 和 Android 实现。这样做的简单性允许您将其附加到应用程序中的任何视图,而无需重新创建代码。


Jos*_*man 3

上网冲浪我找到了解决方案。您应该重现几个步骤。

1) 继承您需要手势的控件(即,如果您想添加手势Xamarin.Forms.Image,请创建您自己的ImageWithLongPressGesture类)。

public class ImageWithLongPressGesture : Xamarin.Forms.Image
{
    public EventHandler LongPressActivated;

    public void HandleLongPress(object sender, EventArgs e)
    {
        //Handle LongPressActivated Event
    }
}
Run Code Online (Sandbox Code Playgroud)

2) 公开所需手势的公共事件。

3)为每个平台创建一个Renderer。

4) 在渲染器中,处理手势并将它们冒泡到您的控件中。

[assembly: ExportRenderer(typeof(ImageWithLongPressGesture), typeof(LongPressGestureRecognizerImageRenderer))]
namespace App1.Droid.DroidRenderers
{
    public class LongPressGestureRecognizerImageRenderer : ImageRenderer
    {
        ImageWithLongPressGesture view;

        public LongPressGestureRecognizerImageRenderer()
        {
            this.LongClick += (sender, args) => {
                Toast.MakeText(this.Context, "Long press is activated.", ToastLength.Short).Show();
            };
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
        {
            base.OnElementChanged(e);

            if(e.NewElement != null)
            {
                view = e.NewElement as ImageWithLongPressGesture;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该解决方案是xamarin 表单论坛上的答案和Telerik 的触摸和手势演示的混合体。