制作类似于新版Google地图iOS应用的向上滑动视图,会遇到多个UIPanGestureRecognizer的麻烦

Bla*_*ode 8 google-maps slideup uiscrollview ios uipangesturerecognizer

我正在尝试重现新iOS Google地图应用程序的上滑菜单的行为.

所以基本上它是一个视图,您可以向上滑动以平移到某个点或向下滑动到某个点.此视图也可以像分页滚动视图一样向右和向左滑动.

它应该向上或向下滚动或向侧面滑动,但不能同时向两侧滑动.

经过大量的研究和测试后,我有一些接近但不太合适的东西.

我的实现是一个UIScrollView,框架为320x400,内容视图为960x400,带有分页滚动.然后我添加一个UIPanGestureRecognizer来处理整个视图的向上滑动.

这是PanRecognizer的handleTouch IBAction:

- (IBAction)handlePan:(UIPanGestureRecognizer *)sender {
NSLog(@"Panning");
    CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
        _firstX = [[sender view] center].x;
        _firstY = [[sender view] center].y;
    }
    if (!IS_IPHONE_5) {
        if (_firstY < 216)
            translatedPoint = CGPointMake(_firstX, 216);
        else
            translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);
    }
    else {
        if (_firstY < 307)
            translatedPoint = CGPointMake(_firstX, 307);
        else
            translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);
    }
    [[sender view] setCenter:translatedPoint];
    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
        CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].y);

        CGFloat finalX = _firstX;
        CGFloat finalY = translatedPoint.y + velocityY;
        if(finalY < _firstY) {
            if (IS_IPHONE_5)
                finalY = 307;
            else
                finalY = 216;
        }
        else if(finalY > _firstY) {

            if (IS_IPHONE_5)
                finalY = 605;
            else
                finalY = 515;
        }

        CGFloat animationDuration = (ABS(velocityY)*.0002)+.2;
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:animationDuration];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        [UIView setAnimationDelegate:self];
        [UIView setAnimationDidStopSelector:@selector(animationDidFinish)];
        [[sender view] setCenter:CGPointMake(finalX, finalY)];
        [UIView commitAnimations];
    }}
Run Code Online (Sandbox Code Playgroud)

所以基本上如果平底锅将视图向上滑动而不是向侧面滑动.我使用这个handlePan方法的问题是我无法使其工作,因此它不允许滚动高于一个点.这就是我正在尝试做的事情:

if (_firstY < 216)
            translatedPoint = CGPointMake(_firstX, 216);
        else
            translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);
Run Code Online (Sandbox Code Playgroud)

最大的问题是UIScrollView平移手势识别器正在处理平移,而不是我添加的平移.这意味着如果我用手指向上滑动视图并将其移动到侧面,UIScrollView会同时向上滑动到两侧.

如果我尝试仅向侧面滑动并将视图向上移动1个像素,我的平移识别器结束并完全滑动视图也会发生同样的情况.

我找到的解决方法是将我的pan识别器设置为要求UIScrollview pan识别器无法工作.

[_panGestureRecognizer requireGestureRecognizerToFail:    _slideUpScrollView.panGestureRecognizer];
Run Code Online (Sandbox Code Playgroud)

所以现在当我向两侧滑动时,它工作并且不会向上移动视图.问题是,只有当你移开手指并且视图没有滚动到两侧时,它才会将自身设置为失败.会发生什么事情,你不能再平移视图了,但是如果你在里面向上滑动,那么如果向上滑动视图就会出现"UIGestureRecognizerStateEnded".

我查看了UIPanGestureRecognizer主题并查看了几个选项,包括将我的pan识别器子类化,使其仅识别滑动平移而不是侧面的那些.

你们我认为我使用正确的策略还是应该以另一种方式看待它?

理想的解决方案是,当记录到侧面的滑动时,它只能水平移动内容并由UIScrollView处理,并且当记录水平平移时,它仅垂直平移并由我的panreconizer处理.Safari具有水平和垂直滚动的相同行为.虽然我没有弄清楚如何实现这一点.

感谢您的阅读,请告诉我您的想法.如果很多应用程序都有像谷歌地图这样的很棒的滑动菜单,那就太棒了!

编辑:我的目标是iOS 6.

Bla*_*ode 4

好吧,我明白了!

我使用了UIPanGestureRecognizer - Only Vertical or Horizo​​ntal中的示例来将我的平移限制为向上和向下垂直滚动,并使其在水平平移时变为失败状态。

我还使用了:限制 UIPanGestureRecognizer 移动来阻止视图向上或向下平移。

最后我将 requireToFail 反转为:

[_slideUpScrollView.panGestureRecognizer requireGestureRecognizerToFail:_panGestureRecognizer];
Run Code Online (Sandbox Code Playgroud)

就这样,它起作用了!

如果您有疑问或有改进建议,请告诉我!

谢谢!

  • 你可以发布这个东西的工作副本(样本)吗? (6认同)