Making a slide up view similar to the new Google Maps iOS app, troubles with multiple UIPanGestureRecognizer

☆樱花仙子☆ 提交于 2019-12-20 09:45:20

问题


I am trying to reproduce the behaviour of the slide up menu of the new iOS Google Maps application.

So basically it's a view that you can slide up with panning up to a certain point or slide down to a certain point. This view can also with sliding to the right and to the left like a paginated scroll view.

It should either scroll up and down or slide to the side but not both at the same time.

After a lot of research and testing I have something that's close but not quite working like need it to.

My implementation is a UIScrollView with a frame of 320x400 and content view of 960x400 with paginated scrolling. Then I add a UIPanGestureRecognizer that handles the slide up of the whole view.

Here is the handleTouch IBAction of the PanRecognizer :

- (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];
    }}

So basically if the pan slide the view up and not to the sides. The problem I have with this handlePan method is that I can't make it work so that it doesn't allow scrolling higher than a point. Which it what I'm trying to do with :

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

The biggest problem thought is that the UIScrollView pan gesture recognizer is handling the pan at the same time than the one I added. Which means the UIScrollView is slided up and to the sides at the same time if I slide up the view with my finger by moving it to the sides as well.

Same is happening if I try to slide to the sides only and move the view up 1 pixel while doing, my pan recognizer ends and slides the view up completely.

The workaround I found is to set my pan recognizer to require the UIScrollview pan recognizer to fail to work.

[_panGestureRecognizer requireGestureRecognizerToFail:    _slideUpScrollView.panGestureRecognizer];

So now when I slide to the sides it works and doesn't move the view up. The problem thought is that it sets itself as failed only when you remove your finger and the view didn't scroll to the sides. What happens is that you can't pan the view up anymore but if you flick up inside it does the goes the "UIGestureRecognizerStateEnded" if and slides the view up.

I looked at UIPanGestureRecognizer topics and looked at few options including, subclassing my pan recognizer to make it recognise only slide up pans and not those of the side.

Do you guys I think I am using the right strategy or should I look at it another way?

The ideal solution would be that when a slide to the side is recorded, it only moves content horizontally and is handle by the UIScrollView and that when an horizontal pan is recorded, it only pans vertically and is handled by my panreconizer. The same behaviour that Safari has with horizontal and vertical scrolling. Though I didn't figure out how to implement that.

Thanks for reading, let me know what you think. It would be great if many apps had a great slide up menu like Google Maps!

Edit : I'm targeting iOS 6.


回答1:


OK, I figured it out!

I used examples from UIPanGestureRecognizer - Only vertical or horizontal to limit my pan to up and down to vertical scrolling and made turn it to state failed when panned horizontally.

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!



来源:https://stackoverflow.com/questions/14307000/making-a-slide-up-view-similar-to-the-new-google-maps-ios-app-troubles-with-mul

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!