首页 > 解决方案 > 为什么 CollectionView 会阻止 SwipeGestureRecognizer?

问题描述

我有一个内容视图,我想在用户向下滑动时执行操作。据我所知,collectionview 会阻止它。因为如果我评论 collectionview 我的操作有效

<ContentView.Content>
        <controls:CustomFrame CornerRadius="25,25,0,0" Margin="0" Padding="10" HorizontalOptions="FillAndExpand"  VerticalOptions="FillAndExpand">
            
                <StackLayout>
                    <StackLayout.GestureRecognizers>
                        <SwipeGestureRecognizer Direction="Down" Swiped="OnSwiped"/>
                    </StackLayout.GestureRecognizers>
                    
                 <CollectionView ItemsSource="{Binding MyPins}"  x:Name="ListPlaces"    
                       SelectionMode="None">

            <CollectionView.ItemsLayout>
                <LinearItemsLayout Orientation="Vertical" ItemSpacing="10"/>
            </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                               <Frame HasShadow="True" HorizontalOptions="FillAndExpand"  BorderColor="#E5E5E5" CornerRadius="10"  VerticalOptions="Start">
                            <StackLayout  Orientation="Vertical">
                                        <StackLayout.GestureRecognizers>
                                            <TapGestureRecognizer  CommandParameter="{Binding .}"    Command="{Binding BindingContext.CallPlace, Source={x:Reference ListPlaces}}"  ></TapGestureRecognizer>
                                        </StackLayout.GestureRecognizers>
                                <Label x:Name="NameOfPlace" Text="{Binding Name}" TextColor="#2D78FD" FontSize="14" FontFamily="Robobo"/>
                               
                        </Frame>
                   
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
                </StackLayout>
           
        </controls:CustomFrame>

    </ContentView.Content>

标签: c#xamlxamarinxamarin.formsxamarin.android

解决方案


您可以使用自定义渲染器来实现它

在表格中

创建自定义 CollectionView

public class MyCollectionView:CollectionView
    {
        public event EventHandler SwipeDown;
        public event EventHandler SwipeUp;

        public void OnSwipeDown() =>
            SwipeDown?.Invoke(this, null);

        public void OnSwipeUp() =>
            SwipeUp?.Invoke(this, null);
    }

在安卓项目中


using Android.Content;

using Android.Views;

using App1;
using App1.Droid;
using System;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(MyCollectionView), typeof(MyCollectionViewRenderer))]
namespace App1.Droid
{
    public class MyCollectionViewRenderer : CollectionViewRenderer
    {
        readonly CustomGestureListener _listener;
        readonly GestureDetector _detector;

        public MyCollectionViewRenderer(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(ElementChangedEventArgs<ItemsView> elementChangedEvent)
        {
            base.OnElementChanged(elementChangedEvent);

            if (elementChangedEvent.NewElement == null)
            {
                _listener.OnSwipeDown -= HandleOnSwipeDown;
                _listener.OnSwipeUp -= HandleOnSwipeUp;
            }

            if (elementChangedEvent.OldElement == null)
            {
                _listener.OnSwipeDown += HandleOnSwipeDown;
                _listener.OnSwipeUp += HandleOnSwipeUp;
            }

            void HandleOnSwipeDown(object sender, EventArgs e) =>
            ((MyCollectionView)Element).OnSwipeDown();

            void HandleOnSwipeUp(object sender, EventArgs e) =>
                ((MyCollectionView)Element).OnSwipeUp();

        }

    }


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

        MotionEvent mLastOnDownEvent;

        public event EventHandler OnSwipeDown;
        public event EventHandler OnSwipeUp;

        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(diffY) > Math.Abs(diffX))
            {
                if (Math.Abs(diffY) > SWIPE_THRESHOLD && Math.Abs(velocityY) > SWIPE_VELOCITY_THRESHOLD)
                {
                    if (diffY > 0)
                        OnSwipeUp?.Invoke(this, null);
                    else
                        OnSwipeDown?.Invoke(this, null);
                }
            }

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

}

在xml中

现在您可以像访问它一样

<StackLayout>
        <local:MyCollectionView SwipeDown="MyCollectionView_SwipeDown" SwipeUp="MyCollectionView_SwipeUp" >
            //...
        </local:MyCollectionView>
</StackLayout>

推荐阅读