简体   繁体   English

Xamarin Forms 向左滑动/向右滑动手势

[英]Xamarin Forms Swipe Left/Swipe Right Gestures

I want to preface this by saying I'm completely new to mobile development, Xamarin, C#, .Net.我想先说我对移动开发、Xamarin、C#、.Net 完全陌生。

I'm working on creating a mobile app using Xamarain Forms and have run into the problem of not having the swipe gesture available to me, at least according to the documentation I've seen.我正在使用 Xamarain Forms 创建一个移动应用程序,但遇到了无法使用滑动手势的问题,至少根据我看到的文档。

I found this site: http://arteksoftware.com/gesture-recognizers-with-xamarin-forms/我找到了这个网站: http : //arteksoftware.com/gesture-recognizers-with-xamarin-forms/

This describes how to add some additional gestures for IOS/Android to be accessible in the context of the form.这描述了如何为 IOS/Android 添加一些额外的手势,以便在表单的上下文中访问。 Before I try to follow this, I wanted to see if anyone else has implemented swipe in a Xamarin Forms app and how they went about it.在我尝试遵循此之前,我想看看是否有人在 Xamarin Forms 应用程序中实现了滑动,以及他们是如何实现的。

My goals are that there has to be a horizontal stack layout.我的目标是必须有一个水平堆栈布局。 This layout contains 7 buttons, each button reflects a day in the current week.此布局包含 7 个按钮,每个按钮反映当前一周中的一天。 Swiping left on the stack layout will change the button's text to the previous week.在堆栈布局上向左滑动会将按钮的文本更改为前一周。 Swiping right will change the button's text to the next week.向右滑动会将按钮的文本更改为下周。

So I'm also trying to use MVVM for this and XAML.所以我也在尝试为此和 XAML 使用 MVVM。 So is it possible for me to separate the swipe left and the swipe right action?那么我可以将向左滑动和向右滑动动作分开吗? I want to use ICommand to pass a certain parameter to a function based on the direction of the swipe.我想使用 ICommand 根据滑动方向将某个参数传递给函数。

Any examples of this or any advice would be greatly appreciated.任何这方面的例子或任何建议将不胜感激。

No need third party libraries.. No need to pay.. Just add these two classes & Implement your swipe listeners不需要第三方库.. 无需付费.. 只需添加这两个类并实现您的滑动监听器

Step 1: Copy paste these two classes第一步:复制粘贴这两个类

SwipeListener.cs SwipeListener.cs

using System;
using Xamarin.Forms;

namespace SwipeLib
{
public class SwipeListener : PanGestureRecognizer
{
    private ISwipeCallBack mISwipeCallback;
    private double translatedX = 0, translatedY = 0;

    public SwipeListener(View view, ISwipeCallBack iSwipeCallBack)
    {
        mISwipeCallback = iSwipeCallBack;
        var panGesture = new PanGestureRecognizer();
        panGesture.PanUpdated += OnPanUpdated;
        view.GestureRecognizers.Add(panGesture);
    }

    void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {

        View Content = (View)sender;

        switch (e.StatusType) {

            case GestureStatus.Running:

                try {
                    translatedX = e.TotalX;
                    translatedY = e.TotalY;
                } catch (Exception err) {
                    System.Diagnostics.Debug.WriteLine("" + err.Message);
                }
                break;

            case GestureStatus.Completed:

                System.Diagnostics.Debug.WriteLine("translatedX : " + translatedX);
                System.Diagnostics.Debug.WriteLine("translatedY : " + translatedY);

                if (translatedX < 0 && Math.Abs(translatedX) > Math.Abs(translatedY)) {
                    mISwipeCallback.onLeftSwipe(Content);
                } else if (translatedX > 0 && translatedX > Math.Abs(translatedY)) {
                    mISwipeCallback.onRightSwipe(Content);
                } else if (translatedY < 0 && Math.Abs(translatedY) > Math.Abs(translatedX)) {
                    mISwipeCallback.onTopSwipe(Content);
                } else if (translatedY > 0 && translatedY > Math.Abs(translatedX)) {
                    mISwipeCallback.onBottomSwipe(Content);
                } else {
                    mISwipeCallback.onNothingSwiped(Content);
                }

                break;

        }
    }

}
}

ISwipeCallBack.cs ISwipeCallBack.cs

using System;
using Xamarin.Forms;
namespace SwipeLib
{  
public interface ISwipeCallBack
{

    void onLeftSwipe(View view);
    void onRightSwipe(View view);
    void onTopSwipe(View view);
    void onBottomSwipe(View view);
    void onNothingSwiped(View view);
}
}

Step 2: From your Xamarin forms pass the view & also interface obj.第 2 步:从您的 Xamarin 表单中传递视图和接口 obj。 Then you get result然后你得到结果

In my case I pass the label就我而言,我通过了标签

 SwipeListener swipeListener = new SwipeListener(lbl_swipe, this);

Step 3: Implement the ISwipeCallBack interface第三步:实现ISwipeCallBack接口

public partial class SwipeLibPage : ContentPage, ISwipeCallBack

Sample project --> https://github.com/rranjithkumar100/Xamarin-Swipe-Library示例项目 --> https://github.com/rranjithkumar100/Xamarin-Swipe-Library

Xamarin.Forms has introduced SwipeGestureRecognizer : Xamarin.Forms 引入了 SwipeGestureRecognizer :

<BoxView Color="Teal" ...>
    <BoxView.GestureRecognizers>
        <SwipeGestureRecognizer Direction="Left" Swiped="OnSwiped"/>
    </BoxView.GestureRecognizers>
</BoxView>

If you're comfortable with paying for a third-party library (and you're using Xamarin Forms, so that's a good possibility), MR.Gestures supports all touch gestures on all Xamarin.Forms Views.如果您愿意为第三方库付费(并且您使用的是 Xamarin Forms,因此很有可能), MR.Gestures支持所有 Xamarin.Forms 视图上的所有触摸手势。 I've used it successfully and been really happy with it.我已经成功地使用了它并且对它非常满意。 It costs a very reasonable €10 and has excellent documentation.它花费非常合理的 10 欧元,并且有很好的文档。

If you're one of the many people who are disappointed that touch gestures aren't supported in Xamarin Forms, consider voting for this suggestion at UserVoice .如果您是对 Xamarin Forms 不支持触​​摸手势感到失望的人之一,请考虑在 UserVoice 上投票支持此建议

You can always have a look at this simple demo.您可以随时查看这个简单的演示。 And use it as follows:并按如下方式使用它:

GestureFrame gi = new GestureFrame
        {
            HorizontalOptions = LayoutOptions.FillAndExpand,
            VerticalOptions = LayoutOptions.FillAndExpand,
            BackgroundColor = Color.FromHex("bf3122"),
        };

        gi.SwipeDown += (s, e) =>
        {
            DisplayAlert("Gesture Info", "Swipe Down Detected", "OK");
            ViewModel.SampleCommand.Execute("Swipe Down Detected");
        };

        gi.SwipeTop += (s, e) =>
        {
            DisplayAlert("Gesture Info", "Swipe Top Detected", "OK");
            ViewModel.SampleCommand.Execute("Swipe Top Detected");
        };

        gi.SwipeLeft += (s, e) =>
        {
            DisplayAlert("Gesture Info", "Swipe Left Detected", "OK");
            ViewModel.SampleCommand.Execute("Swipe Left Detected");
        };

        gi.SwipeRight += (s, e) =>
        {
            DisplayAlert("Gesture Info", "Swipe Right Detected", "OK");
            ViewModel.SampleCommand.Execute("Swipe Right Detected");
        };

        this.Content = gi;

FYI供参考

SwipeView is available in Xamarin.Forms 4.4. SwipeView在 Xamarin.Forms 4.4 中可用。

The SwipeView class also defines four events: SwipeView类还定义了四个事件:

SwipeStarted is fired when a swipe starts. SwipeStarted在开始滑动时触发。 The SwipeStartedEventArgs object that accompanies this event has a SwipeDirection property, of type SwipeDirection.伴随此事件的 SwipeStartedEventArgs 对象具有 SwipeDirection 类型的 SwipeDirection 属性。

SwipeChanging is fired as the swipe moves.当滑动移动时触发SwipeChanging The SwipeChangingEventArgs object that accompanies this event has a SwipeDirection property, of type SwipeDirection, and an Offset property of type double.伴随此事件的 SwipeChangingEventArgs 对象具有 SwipeDirection 类型的 SwipeDirection 属性和 double 类型的 Offset 属性。

SwipeEnded is fired when a swipe ends.当滑动结束时触发SwipeEnded The SwipeEndedEventArgs object that accompanies this event has a SwipeDirection property, of type SwipeDirection.伴随此事件的 SwipeEndedEventArgs 对象具有 SwipeDirection 类型的 SwipeDirection 属性。

CloseRequested is fired when the swipe items are closed. CloseRequested在滑动项关闭时触发。 In addition, SwipeView defines a Close method, which closes the swipe items.此外,SwipeView 定义了一个 Close 方法,用于关闭滑动项。

在此处输入图片说明

For more information about some new Xamarin Forms features visit this link .有关一些新的 Xamarin Forms 功能的详细信息,请访问此链接

Building off of @Ranjith Kumar's solution, I came up with the following:基于@Ranjith Kumar 的解决方案,我想出了以下内容:

public delegate void SwipedEventHandler(ISwipeListener sender, SwipedEventArgs e);

public class SwipedEventArgs : EventArgs
{
    readonly double _x;
    public double X => _x;

    readonly double _y;
    public double Y => _y;

    readonly View _view;
    public View View => _view;

    public SwipedEventArgs(View view, double x, double y)
    {
        _view = view;
        _x = x;
        _y = y;
    }
}

public interface ISwipeListener
{
    event SwipedEventHandler SwipedDown;

    event SwipedEventHandler SwipedLeft;

    event SwipedEventHandler SwipedNothing;

    event SwipedEventHandler SwipedRight;

    event SwipedEventHandler SwipedUp;

    double TotalX
    {
        get;
    }

    double TotalY
    {
        get;
    }
}

public class SwipeListener : PanGestureRecognizer, ISwipeListener
{
    public event SwipedEventHandler SwipedDown;

    public event SwipedEventHandler SwipedLeft;

    public event SwipedEventHandler SwipedNothing;

    public event SwipedEventHandler SwipedRight;

    public event SwipedEventHandler SwipedUp;

    double _totalX = 0, _totalY = 0;

    public double TotalX => _totalX;

    public double TotalY => _totalY;

    readonly View _view;

    public SwipeListener(View view) : base()
    {
        _view = view;
        _view.GestureRecognizers.Add(this);
        PanUpdated += OnPanUpdated;
    }

    void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        switch (e.StatusType)
        {
            case GestureStatus.Running:
                try
                {
                    _totalX = e.TotalX;
                    _totalY = e.TotalY;
                }
                catch (Exception exception)
                {
                    Debug.WriteLine(exception.Message);
                }
                break;

            case GestureStatus.Completed:
                if (_totalX < 0 && Math.Abs(_totalX) > Math.Abs(_totalY))
                {
                    OnSwipedLeft(_totalX, _totalY);
                }
                else if (_totalX > 0 && _totalX > Math.Abs(_totalY))
                {
                    OnSwipedRight(_totalX, _totalY);
                }
                else if (_totalY < 0 && Math.Abs(_totalY) > Math.Abs(_totalX))
                {
                    OnSwipedUp(_totalX, _totalY);
                }
                else if (_totalY > 0 && _totalY > Math.Abs(_totalX))
                {
                    OnSwipedDown(_totalX, _totalY);
                }
                else OnSwipedNothing(_totalX, _totalY);
                break;

        }
    }

    protected virtual void OnSwipedDown(double x, double y)
        => SwipedDown?.Invoke(this, new SwipedEventArgs(_view, x, y));

    protected virtual void OnSwipedLeft(double x, double y)
        => SwipedLeft?.Invoke(this, new SwipedEventArgs(_view, x, y));

    protected virtual void OnSwipedNothing(double x, double y)
        => SwipedNothing?.Invoke(this, new SwipedEventArgs(_view, x, y));

    protected virtual void OnSwipedRight(double x, double y)
        => SwipedRight?.Invoke(this, new SwipedEventArgs(_view, x, y));

    protected virtual void OnSwipedUp(double x, double y)
        => SwipedUp?.Invoke(this, new SwipedEventArgs(_view, x, y));
}

The downside is you can't do anything while the swipe is performed, only after.缺点是你不能在执行滑动时做任何事情,只能在之后。

Maybe that could help someone.也许这可以帮助某人。

I had a problem: there was a ContentPage with scrollview and grid in it.我遇到了一个问题:有一个带有滚动视图和网格的 ContentPage。 All I need to do is to handle swipe left/right gestures.我需要做的就是处理向左/向右滑动的手势。 After searching through google/stackoverflow/github, I found a Nuget package called XamarinFormsGestures .在通过 google/stackoverflow/github 搜索后,我找到了一个名为XamarinFormsGestures的 Nuget 包。 That helped me a lot.这对我帮助很大。 All the instruction is inside the link.所有说明都在链接内。 There is my code:有我的代码:

Vapolia.Lib.Ui.Gesture.SetSwipeLeftCommand(scrollviewgrid, 
new Command(() => { OnLeftSwipe(); })); // What's going on when left swiped.
Vapolia.Lib.Ui.Gesture.SetSwipeRightCommand(scrollviewgrid, 
new Command(() => { OnRightSwipe(); })); // What's going on when right swiped.

You can use the NuGet package "XamarinFormsGesture" of Vapolia (doc available here ).您可以使用 Vapolia 的 NuGet 包“XamarinFormsGesture”(此处提供文档)。 It's free and easy to use.它免费且易于使用。

Available on iOS and Android but it only works on physical devices (not on simulator).在 iOS 和 Android 上可用,但它仅适用于物理设备(不适用于模拟器)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM