如何制作像谷歌地图应用程序一样的向上滑动面板? [英] how to make a sliding up panel like the Google Maps app?

查看:79
本文介绍了如何制作像谷歌地图应用程序一样的向上滑动面板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为iOS寻找 AndroidSlidingUpPanel 之类的内容。我找到了 MBPullDownController ,但它需要两个ViewControllers才能使用,并且需要对应用程序的体系结构进行大的更改我正在努力实施。

I'm looking for something like AndroidSlidingUpPanel for iOS. I found MBPullDownController, but it requires two ViewControllers to use, and requires a big change to the architecture of the app I'm working on to implement.

我只想要在现有视图控制器中添加子视图。我该怎么做呢?

I just want something that adds a subview in an existing view controller. How would I go about doing that?

推荐答案

我在我的iOS应用程序中使用了相当多的滑动面板,我发现了诀窍是将自定义视图添加到故事板(或xib文件)中的视图控制器,但设置其框架使其不在屏幕上。您可以使用布局限制

I use sliding up panels in my iOS apps quite a lot and I've found that the trick is to add a custom view to a view controller in the storyboard (or xib file) but to set its frame so that it is off the screen. You can ensure that the view stays off screen on any device using layout constraints.

然后,这只是在适当的时候在屏幕上设置动画的动画。例如:

Then it's just a case of animating the view on screen when appropriate. e.g.:

- (IBAction)showPanel:(id)sender
{
    // panelShown is an iVar to track the panel state...
    if (!panelShown) {
        // myConstraint is an IBOutlet to the appropriate constraint...
        // Use this method for iOS 8+ otherwise use a frame based animation...
        myConstraint.constant -= customView.frame.size.height;
        [UIView animateWithDuration:0.5 animations:^{
            [self.view setNeedsLayout];
        }];
    }  
    else { 
        myConstraint.constant += customView.frame.size.height;
        [UIView animateWithDuration:0.5 animations:^{
            [self.view setNeedsLayout];
        }];
    }
}

如果您只想向上/向下滑动这将显示您可以使用的面板 UISwipeGestureRecognizer ,如下所示:

If you want to have just a swipe up/down and that will reveal the panel you can use UISwipeGestureRecognizer like so:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // iVar
    swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
    swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
    [self.view addGestureRecognizer:swipeUp];

    // Do the same again with swipeDown using UISwipeGestureRecognizerDirectionDown...
}

- (void)didSwipe:(UIGestureRecognizer *)swipe
{
    if (swipe == swipeUp) {
        // Show panel (see above)...
    } else {
        // Hide panel (see above)...
    }
}

如果您希望面板像您一样跟踪手指显示iOS面板(关闭wifi等)。然后你可以使用 UIPanGestureRecognizer 并获得 translationInView: velocityInView:并相应调整面板。以下是跟踪手指移动的代码片段,但使用 touchesBegan:withEvent: - (void)touchesMoved:withEvent: - (void)touchesEnded:withEvent: UIViewController 中的方法让你尝试一下:

If you want the panel to track your finger like when you show the iOS panel (to turn wifi on an off e.t.c). then you can use UIPanGestureRecognizer and get the translationInView: and velocityInView: and adjust the panel accordingly. Here is a snippet of code that tracks finger movement but using the touchesBegan:withEvent: - (void)touchesMoved:withEvent: and - (void)touchesEnded:withEvent: methods in a UIViewController to give you a taste:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // Don't worry too much about buttonView this is another view that I animate upwards to get out the way of the panel as it slides in from the left...
    [super touchesBegan:touches withEvent:event];
    CGPoint loc = [[touches anyObject] locationInView:self.view];
    // Save last touch for reference...
    lastTouch = loc;
    // leftBeginRect is an area where the user can start to drag the panel...
    // trackFinger defines whether the panel should move with the users gestures or not...
    if (CGRectContainsPoint(leftBeginRect, loc) && canTrack) {
        trackFinger = YES;
    }
    // Left view is a reference to the panel...
    else if (leftView.frame.size.width >= 300) {
        // This means that the panel is shown and therefore should track the user's finger back towards the edge of the screen...
        CGRect frame = CGRectMake(250, 0, 100, self.view.frame.size.height);
        if (CGRectContainsPoint(frame, loc) && canTrack) {
            trackFinger = YES;
        }
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    CGPoint loc = [[touches anyObject] locationInView:self.view];
    // Need to work out the direction in which the user is panning...
    if (lastTouch.x > loc.x) {
        currentFingerDirection = RHFingerDirectionLeft;
    }
    else {
        currentFingerDirection = RHFingerDirectionRight;
    }
    lastTouch = loc;
    if (trackFinger) {
        if (loc.x <= 300) {
            // This means that the panel is somewhere between fully exposed and closed...
            // This is where the frame for the left view (and the constraints) are adjusted according to the user's current finger position...
            CGRect frame = leftView.frame;
            frame.size.width = loc.x;
            [leftView setFrame:frame];
            leftViewConstraint.constant = loc.x;
            if (loc.x <= 80) {
                float percentage = loc.x / 80;
                int amount = 100 * percentage;
                CGRect otherFrame = buttonView.frame;
                otherFrame.origin.y = -amount;
                [buttonView setFrame:otherFrame];
                constraint.constant = constraintConstant + amount;
            }
        }
        else {
            CGRect frame = leftView.frame;
            frame.size.width = 300;
            [leftView setFrame:frame];
            leftViewConstraint.constant = 300;
            frame = buttonView.frame;
            frame.origin.y = -100;
            [buttonView setFrame:frame];
            constraint.constant = constraintConstant + 100;
            trackFinger = NO;
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // This method works out if the panel should pop open or spring closed when the user ends the gesture...
    [super touchesEnded:touches withEvent:event];
    if (trackFinger) {
        CGPoint loc = [[touches anyObject] locationInView:self.view];
        if (loc.x >= 50 && currentFingerDirection == RHFingerDirectionRight) {
            CGRect frame = leftView.frame;
            frame.size.width = 300;
            leftViewConstraint.constant = 300;
            CGRect otherFrame = buttonView.frame;
            otherFrame.origin.y = -100;
            constraint.constant = constraintConstant + 100;
            [UIView animateWithDuration:0.2 animations:^{
                [leftView setFrame:frame];
                [buttonView setFrame:otherFrame];
            }];
        }
        else if (loc.x <= 250 && currentFingerDirection == RHFingerDirectionLeft) {
            CGRect frame = leftView.frame;
            frame.size.width = 0;
            leftViewConstraint.constant = 0;
            CGRect otherFrame = buttonView.frame;
            otherFrame.origin.y = 0;
            constraint.constant = constraintConstant;
            [UIView animateWithDuration:0.2 animations:^{
                [leftView setFrame:frame];
                [buttonView setFrame:otherFrame];
            }];
        }
        else if (loc.x <= 150) {
            CGRect frame = leftView.frame;
            frame.size.width = 0;
            leftViewConstraint.constant = 0;
            CGRect otherFrame = buttonView.frame;
            otherFrame.origin.y = 0;
            constraint.constant = constraintConstant;
            [UIView animateWithDuration:0.2 animations:^{
                [leftView setFrame:frame];
                [buttonView setFrame:otherFrame];
            }];
        }
        else {
            CGRect frame = leftView.frame;
            frame.size.width = 300;
            leftViewConstraint.constant = 300;
            CGRect otherFrame = buttonView.frame;
            otherFrame.origin.y = -100;
            constraint.constant = constraintConstant + 100;
            [UIView animateWithDuration:0.2 animations:^{
                [leftView setFrame:frame];
                [buttonView setFrame:otherFrame];
            }];
        }
        trackFinger = NO;
    }
    currentFingerDirection = RHFingerDirectionNone;
}

代码非常复杂,但它会产生一个漂亮的面板动画,跟随你的手指非常像iOS面板。

The code is quite involved but it results in a nice panel animation that follows your finger very like the iOS panel.

这篇关于如何制作像谷歌地图应用程序一样的向上滑动面板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆