8

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

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

它应该上下滚动或滑动到一边,但不能同时滚动。

经过大量的研究和测试,我得到了一些接近但并不像需要它那样工作的东西。

我的实现是一个 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];
    }}

所以基本上如果平底锅向上滑动视图而不是向侧面滑动。这个handlePan 方法的问题是我不能让它工作,所以它不允许滚动到一个点以上。这是我想要做的:

if (_firstY < 216)
            translatedPoint = CGPointMake(_firstX, 216);
        else
            translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);

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

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

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

[_panGestureRecognizer requireGestureRecognizerToFail:    _slideUpScrollView.panGestureRecognizer];

所以现在当我滑动到两侧时它可以工作并且不会向上移动视图。问题的想法是,只有当您移开手指并且视图没有滚动到两侧时,它才会将自己设置为失败。发生的情况是,您无法再向上平移视图,但如果您在其中向上滑动,则会出现“UIGestureRecognizerStateEnded”,并且向上滑动视图。

我查看了 UIPanGestureRecognizer 主题并查看了一些选项,包括将我的平移识别器子类化以使其仅识别上滑的平移而不是侧面的平移。

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

理想的解决方案是,当录制到侧面的幻灯片时,它只会水平移动内容并由 UIScrollView 处理,而当录制水平平移时,它只会垂直平移并由我的 panreconizer 处理。Safari 的水平和垂直滚动行为相同。虽然我没有弄清楚如何实现它。

感谢阅读,让我知道你的想法。如果许多应用程序都有像 Google 地图这样的上滑菜单,那就太好了!

编辑:我的目标是 iOS 6。

4

1 回答 1

4

好的,我想通了!

我使用了UIPanGestureRecognizer 中的示例 - 只有垂直或水平才能将我的平移限制为向上和向下垂直滚动,并在水平平移时将其设置为失败状态。

I also used : Restricting UIPanGestureRecognizer movement to block the view from panning to far up or down.

Finally I reversed the requiresToFail to :

[_slideUpScrollView.panGestureRecognizer requireGestureRecognizerToFail:_panGestureRecognizer];

And there it works!

Let me know if you have questions or have improvements to propose!

Thanks!

于 2013-01-26T15:44:56.700 回答