滚动视图移动时,Xamarin UIScrollView GestureRecognizerShouldBegin报告速度为0

时间:2015-10-26 13:21:17

标签: ios xamarin uiscrollview xamarin.ios uigesturerecognizer

我正在使用Xamarin开发iOS应用程序,我想继承UIScrollView,以便根据其速度处理滚动视图中的平移手势。所以,我覆盖了GestureRecognizerShouldBegin并检查了平移手势的VelocityInView。这适用于第一个手势,但在滚动视图处于运动状态(减速)时触发的后续平移手势始终报告速度为(0,0):

public class MyScroll : UIScrollView
{
    public override bool GestureRecognizerShouldBegin(UIGestureRecognizer gestureRecognizer)
    {
        UIPanGestureRecognizer panGesture = gestureRecognizer as UIPanGestureRecognizer;
        if (panGesture != null)
        {
            CGPoint velocity = panGesture.VelocityInView(this);
            Console.WriteLine("Pan gesture velocity: " + velocity);
        }
        return true;
    }
}

滚动运动后平移一次然后再次输出:

Pan gesture velocity: {X=37.92359, Y=-872.2426}
Pan gesture velocity: {X=0, Y=0}

这是一个错误还是预期的行为?

编辑:在Xamarin的论坛上交叉发布:https://forums.xamarin.com/discussion/54478/uiscrollview-pan-gesture-velocity-reporting-0-if-it-is-already-moving#latest

修改以澄清:

澄清我最终要做的事情:我在水平分页视图中有一个垂直滚动视图。我想检查平底锅的速度,这样我就可以告诉滚动视图如果平底锅是水平的" (即,X速度> Y速度)。默认行为是,一旦滚动视图处于运动状态,另一个手势仍会滚动,但这使得用户难以水平滚动(跨页面),直到垂直滚动完全结束。

2 个答案:

答案 0 :(得分:2)

我终于明白了。感谢@RobertN的帮助:)

关键是滚动视图使用的默认平移手势识别器将始终报告0速度(如果它已经在运动中)(例如,来自先前手势的惯性仍然有效)。添加新的UIPanGestureRecognizer是录制"实际"的好方法。后续手势的速度,但到那时,影响原始平移手势GestureRecognizerShouldBegin为时已晚。所以我要做的就是在我的新ShouldBegin添加一个UIPanGestureRecognizer委托,并使用 返回false,以便我希望手势为& #34;堕落"到父寻呼机。

        public MyScroll() : base()
        {
            UIPanGestureRecognizer panGesture = new UIPanGestureRecognizer();

            panGesture.ShouldBegin = delegate(UIGestureRecognizer recognizer)
            {
                CGPoint v = panGesture.VelocityInView(this);

                if (v.X != 0 || v.Y != 0)
                {
                    if (Math.Abs(v.X) > Math.Abs(v.Y))
                    {
                        return false;
                    }
                }

                return true;
            };

            this.AddGestureRecognizer(panGesture);
        }

这样,我只是让默认滚动视图平移手势识别器完成它的工作,而我的新UIPanGestureRecognizer识别用户何时进行新的水平手势,然后通过该手势以便寻呼机可以寻呼。这使得父寻呼机和垂直页面滚动视图的组合可以很好地一起操作(想象具有垂直滚动页面并且能够翻页,即使垂直页面处于运动中)。注意,您还需要实现以下方法以允许两个手势识别器同时操作:

        [Export("gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:")]
        public bool ShouldRecognizeSimultaneously(UIGestureRecognizer gestureRecognizer, UIGestureRecognizer otherGestureRecognizer)
        {
            return true;
        }

答案 1 :(得分:0)

  

这是一个错误还是预期的行为?

在通过GestureRecognizerShouldBegin上的VelocityInView获取p / s方面,在平移动作开始后获得0,0 但未停止/重置,预计至少在我的经验中。 Obj-C / Swift将返回同样的东西,不要问我为什么,必须得到一个真正的iOS开发人员来询问那个原因。

在任何地方抓住速度'你应该是金色的,如果你真的需要在GestureRecognizerShouldBegin内从任何其他的泛识别器中分配你的UIScrollView子类中的私有CGPoint(我在下面的例子中这样做) ...

示例输出:

2015-10-26 12:07:06.676 iOSVelocity[68486:2309184] Touch-enabed Pan gesture velocity: {X=-608.4813, Y=0}
2015-10-26 12:07:06.703 iOSVelocity[68486:2309184] Touch-enabed Pan gesture velocity: {X=-1213.629, Y=0}
2015-10-26 12:07:06.726 iOSVelocity[68486:2309184] Touch-enabed Pan gesture velocity: {X=-935.5507, Y=0}
2015-10-26 12:07:06.771 iOSVelocity[68486:2309184] Touch-enabed Pan gesture velocity: {X=-1191.385, Y=-8.564461}
2015-10-26 12:07:06.772 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=-1191.385, Y=-8.564461}
2015-10-26 12:07:06.772 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=-1191.385, Y=-8.564461}
2015-10-26 12:07:08.882 iOSVelocity[68486:2309184] !!!! ShouldBegin velocity not reset !!!!
2015-10-26 12:07:08.885 iOSVelocity[68486:2309184] GestureRecognizerShouldBegin velocity: {X=-1191.385, Y=-8.564461}
2015-10-26 12:07:08.887 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=-1191.385, Y=-8.564461}
2015-10-26 12:07:08.889 iOSVelocity[68486:2309184] gestureRecognizer velocity: {X=0, Y=0}
2015-10-26 12:07:08.890 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=0, Y=0}
2015-10-26 12:07:08.891 iOSVelocity[68486:2309184] gestureRecognizer velocity: {X=0, Y=0}
2015-10-26 12:07:08.937 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=0, Y=0}
2015-10-26 12:07:08.938 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=0, Y=0}
2015-10-26 12:07:08.939 iOSVelocity[68486:2309184] gestureRecognizer velocity: {X=-336.9197, Y=0}
2015-10-26 12:07:08.940 iOSVelocity[68486:2309184] Touch-enabled Pan gesture velocity: {X=-336.9197, Y=0}
2015-10-26 12:07:08.954 iOSVelocity[68486:2309184] Touch-enabled Pan gesture velocity: {X=-650.7258, Y=0}
2015-10-26 12:07:08.961 iOSVelocity[68486:2309184] Touch-enabled Pan gesture velocity: {X=-650.7258, Y=0}
2015-10-26 12:07:08.993 iOSVelocity[68486:2309184] Touch-enabled Pan gesture velocity: {X=-914.0547, Y=0}
2015-10-26 12:07:09.027 iOSVelocity[68486:2309184] Touch-enabled Pan gesture velocity: {X=-734.1516, Y=0}
2015-10-26 12:07:09.032 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=-734.1516, Y=0}
2015-10-26 12:07:09.033 iOSVelocity[68486:2309184] otherGestureRecognizer velocity: {X=-734.1516, Y=0}
2015-10-26 12:07:09.060 iOSVelocity[68486:2309184] Touch-enabled Pan gesture velocity: {X=-1086.368, Y=0}

示例UIScrollView子类:

注意:这会使用shouldRecognizeSimultaneouslyWithGestureRecognizer以便在用户提起触摸后继续自动平移

注意2:不确定我是否捕获了所有手势状态排列,因此根据需要进行调整

using System;
using UIKit;
using CoreGraphics;
using CoreFoundation;
using CoreData;
using Foundation;
using CoreMotion;

namespace iOSVelocity
{
    public class MyScroll : UIScrollView
    {
        UIPanGestureRecognizer panGesture;
        CGPoint velocity;

        public MyScroll (CGRect cGRect) : base (cGRect)
        {
            panGesture = new UIPanGestureRecognizer (() => {
                if ((panGesture.State == UIGestureRecognizerState.Began || panGesture.State == UIGestureRecognizerState.Changed) && (panGesture.NumberOfTouches == 1)) {
                    velocity = panGesture.VelocityInView (this);
                    Console.WriteLine ("Touch-enabled Pan gesture velocity: " + velocity);
                } else if (panGesture.State == UIGestureRecognizerState.Ended) {
                    // Gesture ended, but auto-panning could still be going... 
                }
            });
            AddGestureRecognizer (panGesture);
        }

        [Export ("gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:")]
        public bool ShouldRecognizeSimultaneously (UIGestureRecognizer gestureRecognizer, UIGestureRecognizer otherGestureRecognizer)
        {
            if (gestureRecognizer is UIPanGestureRecognizer) {
                var panRecognizer = (UIPanGestureRecognizer)gestureRecognizer;
                velocity = panRecognizer.VelocityInView (this);
                Console.WriteLine ("gestureRecognizer velocity: " + velocity);
            } else if (otherGestureRecognizer is UIPanGestureRecognizer) {
                var panRecognizer2 = (UIPanGestureRecognizer)otherGestureRecognizer;
                CGPoint beginvelocity = panRecognizer2.VelocityInView(this);
                if (beginvelocity.X != 0 && beginvelocity.Y != 0)
                    velocity = panRecognizer2.VelocityInView (this);
                Console.WriteLine ("otherGestureRecognizer velocity: " + velocity);
            } else {
                // What should we do here?
            }
            return true;
        }

        public override bool GestureRecognizerShouldBegin (UIGestureRecognizer gestureRecognizer)
        {
            UIPanGestureRecognizer panGesture = gestureRecognizer as UIPanGestureRecognizer;
            if (panGesture != null) {
                CGPoint beginvelocity = panGesture.VelocityInView(this);
                if (beginvelocity.X == 0 && beginvelocity.Y == 0) {
                    Console.WriteLine ("!!!! ShouldBegin velocity not reset !!!!");
                } else {
                    velocity = beginvelocity;
                }
                Console.WriteLine ("GestureRecognizerShouldBegin velocity: " + velocity);
            }
            return true;
        }
    }
}