首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SwipeGestureRecognizer表单:如何为StackLayout添加StackLayout?

SwipeGestureRecognizer表单:如何为StackLayout添加StackLayout?
EN

Stack Overflow用户
提问于 2019-12-05 06:05:05
回答 2查看 2.8K关注 0票数 1

我的主页上有15个选项。最初,我将在UI中显示9个选项。若要查看其余6个图标,用户可以向右滑动,然后向左滑动以查看前面的内容。我试图实现如下所示的刷卡功能,但它不起作用。

XAML

代码语言:javascript
运行
复制
<StackLayout x:Name="firstLlayout">
    <Grid>
        //3 icons in horizontal
    </Grid>

    <Grid>
        //3 icons in horizontal
    </Grid>

    <Grid>
        //3 icons in horizontal
    </Grid>
    <StackLayout.GestureRecognizers>
        <SwipeGestureRecognizer Direction="Right" Swiped="RightSwipe"/>
    </StackLayout.GestureRecognizers>
</StackLayout>

<StackLayout IsVisible="False" x:Name="secondLayout">
     <Grid>
        //3 icons in horizontal
    </Grid>

    <Grid>
        //3 icons in horizontal
    </Grid>
    <StackLayout.GestureRecognizers>
        <SwipeGestureRecognizer Direction="Left" Swiped="LeftSwipe"/>
    </StackLayout.GestureRecognizers>
</StackLayout>

XAML.CS

代码语言:javascript
运行
复制
public void RightSwipe(object sender, EventArgs e)
{
    firstLlayout.IsVisible = false;
    secondLayout.IsVisible = true;
}

public void LeftSwipe(object sender, EventArgs e)
{
    secondLayout.IsVisible = false;
    firstLlayout.IsVisible = true;
}

当尝试向左和右滑动时,UI中什么都不会发生,代码执行也不会出现在事件函数中。我在这里错过了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-05 07:56:49

Cause1:

如果将堆栈布局放置在ScrollView中,则Swipe操作将与滚动操作发生冲突。

解决方案:

从根ScrollView中删除StackLayout,然后滑动将工作。

Cause2:需要向StackLayout添加子控件(如图像或标签),否则将永远不会调用swipe操作。

解决方案:--如果您想让StackLayout的内容默认不显示,可以检查以下代码。

在代码后面

代码语言:javascript
运行
复制
using System;
using Xamarin.Forms;

namespace xxx
{
    public class GestureScrollView : ScrollView
    {
        public event EventHandler SwipeLeft;
        public event EventHandler SwipeRight;

        public void OnSwipeLeft() =>
            SwipeLeft?.Invoke(this, null);

        public void OnSwipeRight() =>
            SwipeRight?.Invoke(this, null);
    }
}

在Android项目中

代码语言:javascript
运行
复制
using System;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using xxx;
using xxx.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(GestureScrollView), typeof(GestureScrollViewRenderer))]
namespace xxx.Droid
{
    public class GestureScrollViewRenderer : ScrollViewRenderer
    {
        readonly CustomGestureListener _listener;
        readonly GestureDetector _detector;

        public GestureScrollViewRenderer(Context context) : base(context)
        {
            _listener = new CustomGestureListener();
            _detector = new GestureDetector(context, _listener);
        }

        public override bool DispatchTouchEvent(MotionEvent e)
        {
            if (_detector != null)
            {
                _detector.OnTouchEvent(e);
                base.DispatchTouchEvent(e);
                return true;
            }

            return base.DispatchTouchEvent(e);
        }

        public override bool OnTouchEvent(MotionEvent ev)
        {
            base.OnTouchEvent(ev);

            if (_detector != null)
                return _detector.OnTouchEvent(ev);

            return false;
        }

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.NewElement == null)
            {
                _listener.OnSwipeLeft -= HandleOnSwipeLeft;
                _listener.OnSwipeRight -= HandleOnSwipeRight;
            }

            if (e.OldElement == null)
            {
                _listener.OnSwipeLeft += HandleOnSwipeLeft;
                _listener.OnSwipeRight += HandleOnSwipeRight;
            }
        }

        void HandleOnSwipeLeft(object sender, EventArgs e) =>
            ((GestureScrollView)Element).OnSwipeLeft();

        void HandleOnSwipeRight(object sender, EventArgs e) =>
            ((GestureScrollView)Element).OnSwipeRight();
    }

    public class CustomGestureListener : GestureDetector.SimpleOnGestureListener
    {
        static readonly int SWIPE_THRESHOLD = 100;
        static readonly int SWIPE_VELOCITY_THRESHOLD = 100;

        MotionEvent mLastOnDownEvent;

        public event EventHandler OnSwipeLeft;
        public event EventHandler OnSwipeRight;

        public override bool OnDown(MotionEvent e)
        {
            mLastOnDownEvent = e;

            return true;
        }

        public override bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
        {
            if (e1 == null)
                e1 = mLastOnDownEvent;

            float diffY = e2.GetY() - e1.GetY();
            float diffX = e2.GetX() - e1.GetX();

            if (Math.Abs(diffX) > Math.Abs(diffY))
            {
                if (Math.Abs(diffX) > SWIPE_THRESHOLD && Math.Abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
                {
                    if (diffX > 0)
                        OnSwipeRight?.Invoke(this, null);
                    else
                        OnSwipeLeft?.Invoke(this, null);
                }
            }

            return base.OnFling(e1, e2, velocityX, velocityY);
        }
    }
}

在Xaml中

将StackLayout放在ScrollView中

代码语言:javascript
运行
复制
<local:GestureScrollView SwipeRight="RightSwipe">
     <StackLayout x:Name="firstLlayout" >

        //...        
     </StackLayout>

          
</local:GestureScrollView>
票数 2
EN

Stack Overflow用户

发布于 2022-02-20 04:07:59

对于这个问题,我喜欢并使用了Lucas Zhang的答案answer-59190549,但是,GestureScrollView可以更改为使用iOS将使用的相同的GestureRecognizer:

代码语言:javascript
运行
复制
public class GestureScrollView : ScrollView
{
    private bool isInitialized = false;
    private List<SwipeGestureRecognizer> LeftSwipeRecognizers { get; } = new();
    private List<SwipeGestureRecognizer> RightSwipeRecognizers { get; } = new();

    public GestureScrollView() : base()
    {
    }

    protected override void LayoutChildren(double x, double y, double width, double height)
    {
        base.LayoutChildren(x, y, width, height);

        //Not sure if this is the best place, but the ctor wasn't getting called.
        if (!isInitialized)
        {
            isInitialized = true;
            foreach (SwipeGestureRecognizer swipeGestureRecognizer in GestureRecognizers.Where(x => x is SwipeGestureRecognizer))
            {
                if (swipeGestureRecognizer.Direction.HasFlag(SwipeDirection.Left))
                {
                    LeftSwipeRecognizers.Add(swipeGestureRecognizer);
                }

                if (swipeGestureRecognizer.Direction.HasFlag(SwipeDirection.Right))
                {
                    RightSwipeRecognizers.Add(swipeGestureRecognizer);
                }
            }
        }
    }

    private void ExecuteGestureCommands(List<SwipeGestureRecognizer> swipeRecognizers, SwipedEventArgs e)
    {
        foreach (var gesture in swipeRecognizers)
        {
            gesture.SendSwiped(this, e.Direction);
        }
    }

    public void OnSwipeLeft(object sender, SwipedEventArgs e)
    {
        ExecuteGestureCommands(LeftSwipeRecognizers, e);
    }

    public void OnSwipeRight(object sender, SwipedEventArgs e)
    {
        ExecuteGestureCommands(RightSwipeRecognizers, e);
    }
}

而且渲染器需要类似的更改(基本上将所有"EventArgs“引用更改为" SwipedEventArgs”,并在事件调用中传递一个新的SwipedEventArgs):

代码语言:javascript
运行
复制
... 
void HandleOnSwipeLeft(object sender, SwipedEventArgs e) => ((GestureScrollView)Element).OnSwipeLeft(sender, e);
void HandleOnSwipeRight(object sender, SwipedEventArgs e) => ((GestureScrollView)Element).OnSwipeRight(sender, e);
...
public event EventHandler<SwipedEventArgs> OnSwipeLeft;
public event EventHandler<SwipedEventArgs> OnSwipeRight;
...
if (diffX > 0)
{
    OnSwipeRight?.Invoke(this, new SwipedEventArgs(null, SwipeDirection.Right));
}
else
{
    OnSwipeLeft?.Invoke(this, new SwipedEventArgs(null, SwipeDirection.Left));
}
...

它并不完美,因为它忽略了Android中的上/下方向,但其他实现也是如此。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59189164

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档