How to accomplish a “90% slide” between two UIView

2019-06-02 16:21发布

问题:

I have a particular scenario that I'm trying to emulate and, being fairly new to Cocoa Touch, I'm not sure of the best way to accomplish it. Pardon my lacking tactical knowledge; hopefully some clear exposition will help.

What I'd Like To Emulate:

The app I'm looking at (in particular) is Beat. Below is an example of one of their UIViews - in particular, notice the gear icon for Settings at the bottom.

When that gear is touched or swiped up, two primary UIView changes occur:

  1. The original UIView is slid up the screen about 90% of the way (the key point being that it does not slide all the way up).
  2. A new UIView is slid up to fill that newly vacated 90% space.

This is the basic functionality that I would like to accomplish.

Implementation Idea #1: Single UIViewController w/ Multiple UIViews

At first, I considered having a single UIViewController manage both the "main" and the "settings" views. In that case, it would be a fairly simple thing to transition these views in the appropriate manner.

That said, this seems a bit cluttered to me. Depending on how robust my two sets of functionality are, that's a recipe to overload a single UIViewController. You might tell me that that's okay, but off the bat, it seems too much.

Implementation Idea #2: Multiple UIViewControllers Within Custom Container ViewController

This is the route I'm currently going down. It separates the two discrete sets of functionality into separate UIViewControllers (contained within a Container ViewController) and transitions between the two via:

- (void)flipFromViewController:(UIViewController *)fromController
              toViewController:(UIViewController *)toController
{
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height;

    fromController.view.frame = CGRectMake(0.0f, 0.0f, width, height);
    toController.view.frame = CGRectMake(0.0f, height, width, height);

    [self addChildViewController:toController];
    [fromController willMoveToParentViewController:nil];

    [self transitionFromViewController:fromController
                      toViewController:toController
                              duration:0.5f
                               options:UIViewAnimationOptionTransitionNone
                            animations:^(void) {
                                fromController.view.frame = CGRectMake(0.0f, -(height - 100.0f), width, height);
                                toController.view.frame = CGRectMake(0.0f, 100.0f, width, height);
                            }
                            completion:^(BOOL finished) {
                                [fromController removeFromParentViewController];
                                [toController didMoveToParentViewController:self];
                            }];
}

The problem with this is the transition: it doesn't seem to stop "90% of the way". It looks more like it's intended to completely transition out an "old" controller and in a "new" controller, even though my frame adjustments on the two UIViews are not supposed to be "complete" moves.

Where I'd Like Guidance

I'm not asking for a complete solution - your expertise would be too expensive. :) That said, being fairly new to this, I would love your insight on what the right approach would be. Please let me know if I can provide further information.

Thanks!

回答1:

I do think your 2nd method is on the right track, and your intuition about using transitionFromViewController:ToViewController is also right -- I wouldn't use that method if you want both view controllers to be present and active. So, I would have the controller with the gear view be a child view controller of a custom container controller, then add the second child off screen to the bottom like you have. Then animate both views up using animateWithDuration:... At the end of that, animation, you should have what you want, and you container controller will have two children.