Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swipe to move a container view controller in from off screen

I have a main view controller, and on that view controller sits a little UIImageView. I want to be able to swipe that image view and have a contained view controller slide (animated) onto the screen, sort of like pulling the tab of a manilla folder.

I've tried every which way of achieving this, and I cannot find a solution! Particularly because I want the new view controller to come from offscreen, and I'm using storyboards.

Here is the the normal state of the view controller:

A user should be able to swipe the image view, which slides a new view controller on screen. The end of the slide animate should look like this:

Does anyone know how this can be achieved? I don't know if using a container is right, but that's just the best way I came up with to do it.

like image 680
samuelb Avatar asked Dec 06 '22 04:12

samuelb


1 Answers

This should be easy. Create a container view controller. Create the child view controller and control-drag an embed segue from the container view controller to the child view controller. That will cause the child view controller's view to be installed in the parent during viewDidLoad.

Now control-drag from your container view into the header file of your parent view controller to create an IBOutlet.

Drag the container view off-screen to the right. You can also use the size inspector to increase the X coordinate of the child view until it is just off-screen.

Now add a swipe gesture recognizer to your parent view controller's view, and connect it to a method (I call the methods from gesture recognizers IBActions even though they don't have to be IBActions.)

In the action method, use a UIView animation block to decrease the X coordinate of the container view's frame by it's width. That will animate it onto the screen.

(Alternately, you could use a pan gesture recognizer as the other poster suggested, and move the container view as the user drags. If you do that you would have to add code that only moves the container view to the right, not up/down/left, and stops moving it once it gets to it's final position.)

Update for Auto-Layout:


Note that with AutoLayout you should really manage the position of the container view with constraints.

You'd create a constraint that placed the view where you wanted it, and control-drag from that constraint into your code to make an outlet to it.

You'd then add a constant offset to the constraint that was enough to push the container view off-screen (if the container view is flush with the right edge of the screen then you'd just add the width of the container view to the contstraint constant, shifting the view to the right by it's width, and just off-screen.

When it's time to animate the view back on-screen you'd set the constraint constant back to it's original value (probably zero) and then call layoutIfNeeded in an animation block.

Objective-C:

IBOutlet NSLayoutConstraint *containerViewXConstraint;

Your updated IBAction method might look like this:

- (IBAction)slideView: (id) sender {
  containerViewXConstraint.constant = 0;  //Move the view on-screen
  [UIView animateWithDuration: 0.2
    animations: ^ {
      //animate the layout change
      [self.view layoutIfNeeded];
    }
  ]
}

In Swift 3:

@IBAction func slideView(_ sender: AnyObject) {
  containerViewXConstraint.constant = 0  //Move the view on-screen
  UIViewanimateWithDuration(0.2) {
      //animate the layout change
      self.view.layoutIfNeeded()
    }
}
like image 181
Duncan C Avatar answered Dec 11 '22 10:12

Duncan C