Search code examples
iosswiftuiviewsubviewanimatewithduration

UIView slide transitions, help needed & near-working code


I'm looking to do the following fully programmatically and have some code that ALMOST does it!

Goal

  1. Transition between two master views, viewOne and viewTwo. 'viewOne' is the initial full-screen view.

  2. Transition with a slide of differing direction and type

    a. using either left/right or up/down specifically

    b. be able to select direction (e.g. 'up' or 'down')

Observed Code Response

  1. [Good] The code below successfully transitions between views

  2. [Problem] The code below only ever uses the same transition, every time Left->Right!

Core Code

(remaining code segments posted below in a second block)

    func pick_view(showFirst: Bool) {

        let addedView   = (showFirst) ? viewOne : viewTwo;
        let removedView = (showFirst) ? viewTwo : viewOne;

        print("picking a new view");

        //let animationType = (showFirst) ? UIViewAnimationOptions.TransitionFlipFromLeft : .TransitionFlipFromRight; //flip L->R or R-> depending

        addedView.alpha = 0;

        self.view.addSubview(addedView);

        print("old view off!");


        UIView.animateWithDuration(0.5, delay: 0.5, options: .TransitionCurlUp, animations: {  //.CurveLinear is an option too

            print("new view added");

            addedView.alpha = 1.0;

            addedView.frame = self.view.frame;

            }, completion: { (finished: Bool) -> Void in

                print("old view removed");

                removedView.frame = CGRectMake(self.view.frame.width, 0, 0, 0);

                removedView.removeFromSuperview();
        });

        UIView.commitAnimations();

        return;
    }

Remaining Code Segments

Recall that this is 100% programmatic. As such I feel this code here is exceptionally high value to be able to respond :)

import UIKit

class ViewController: UIViewController {

    var viewOne : UIView!;
    var viewTwo : UIView!;

    override func viewDidLoad() {
        super.viewDidLoad();

        gen_views();
        pick_view(true);

        return;
    }

    func gen_views() {

        viewOne = UIView();
        viewOne.backgroundColor = UIColor.redColor();
        viewOne.frame = self.view.frame;

        addSecondUIView(viewOne, dispStr: "4:30 PM");
        addSubviewButton(viewOne, return_msg: "Launch View #2", action_fcn:  "press_launch:");

        viewTwo = UIView();
        viewTwo.backgroundColor = UIColor.blueColor();
        viewTwo.frame = self.view.frame;

        addSecondUIView(viewTwo, dispStr: "8:00 PM");
        addSubviewButton(viewTwo, return_msg: "Return from View #2", action_fcn:  "press_return:");

        viewTwo.frame = CGRectMake(self.view.frame.width, 0, 0, 0);       //init off-screen

        self.view.addSubview(viewOne);                                    //add em both!
        self.view.addSubview(viewTwo);

        return;
    }


    func pick_view(showFirst: Bool) {        
        //see above :)
    }


    func addSecondUIView(aView: UIView, dispStr : String) {

        let anotherView : UIView = UIView(frame: CGRect(x: 20, y:60, width: 100, height: 50));

        anotherView.backgroundColor = UIColor.grayColor();

        anotherView.layer.cornerRadius = 15;

        let someLabel : UILabel = UILabel(frame: CGRect(x:5, y: 0, width: anotherView.frame.width, height:  anotherView.frame.height));

        someLabel.font  =   UIFont(name: "HelveticaNeue", size: 23);
        someLabel.text  =   dispStr;
        someLabel.textColor     = UIColor.whiteColor();
        someLabel.textAlignment = NSTextAlignment.Center;

        anotherView.addSubview(someLabel);

        aView.addSubview(anotherView);

        return;
    }


    func addSubviewButton(aView: UIView, return_msg: String, action_fcn : Selector) {

        let newButton : UIButton = UIButton(type: UIButtonType.RoundedRect);

        newButton.translatesAutoresizingMaskIntoConstraints = true;                     //must be true for center to work

        newButton.setTitle(return_msg,      forState: UIControlState.Normal);
        newButton.backgroundColor = UIColor.whiteColor();

        //newButton.frame = CGRectMake(0, 0, 144, 30);                                  // or just use sizeToFit(), it's easier!
        newButton.sizeToFit();
        newButton.center = CGPointMake((UIScreen.mainScreen().bounds.width)/2, 250);     //must call after it's sized or won't work!

        //actions
        newButton.addTarget(self, action: action_fcn, forControlEvents:  .TouchUpInside);

        //add!
        aView.addSubview(newButton);

        return;
    }


    func press_launch(sender: UIButton!) {

        print("\(sender.titleLabel!.text!) was pressed and press_launch called");

        pick_view(false);

        return;
    }


    func press_return(sender: UIButton!) {
        print("\(sender.titleLabel!.text!) was pressed and press_return called");

        pick_view(true);

        return;
    }


    override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning(); }
}

Solution

  • Solved! Thank you Zach B!!!!

    Here are the key changes made to the originating code for solution

    • (Transition Type) UIViewAnimationOptions.TransitionCrossDissolve was used for 'options:'
    • (Transition Direction) Set by the initial offscreen location of view! See xRemoved in pick_view() for a clear example

    And that's it!!!

    For clarity and cleanliness of future inspection here is the final working solution:

    class ViewController: UIViewController {
    
        var viewOne : UIView!;
        var viewTwo : UIView!;
    
    override func viewDidLoad() {
        super.viewDidLoad();
    
        gen_views();
        pick_view(true);
    
        return;
    }
    
    func gen_views() {
    
        viewOne = UIView();
        viewOne.backgroundColor = UIColor.redColor();
        viewOne.frame = self.view.frame;
    
        addSecondUIView(viewOne, dispStr: "4:30 PM");
        addSubviewButton(viewOne, return_msg: "Launch View #1", action_fcn:  "press_launch:");
    
        viewTwo = UIView();
        viewTwo.backgroundColor = UIColor.blueColor();
        viewTwo.frame = self.view.frame;
    
        addSecondUIView(viewTwo, dispStr: "8:00 PM");
        addSubviewButton(viewTwo, return_msg: "Return from View #2", action_fcn:  "press_return:");
    
        viewOne.frame = self.view.frame;
        viewTwo.frame = CGRectMake(self.view.frame.width, 0, self.view.frame.width, self.view.frame.height);       //init off-screen
    
        self.view.addSubview(viewOne);                                    //add em both!
            self.view.addSubview(viewTwo);
    
            return;
    }
    
        /**********************************************************************************************************************/
        /* @url    http://www.raywenderlich.com/86521/how-to-make-a-view-controller-transition-animation-like-in-the-ping-app */
        /**********************************************************************************************************************/
        func pick_view(showFirst: Bool) {
    
            let addedView   = (showFirst) ? viewOne : viewTwo;
            let removedView = (showFirst) ? viewTwo : viewOne;
    
            let xRemoved    = (showFirst) ? self.view.frame.width : -self.view.frame.width; // sets which dir it slides into view from
    
            addedView.alpha = 0;
    
            self.view.addSubview(addedView);
    
            print("old view off!");
    
            UIView.animateWithDuration(0.5, delay: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
    
                print("new view added");
    
                addedView.alpha = 1.0;
    
                addedView.frame = self.view.frame;
    
                }, completion: { (finished: Bool) -> Void in
    
                    print("old view removed");
    
                    removedView.frame = CGRectMake(xRemoved, 0, self.view.frame.width, self.view.frame.height);
    
                    removedView.removeFromSuperview();
            })
    
            return;
        }
    
    
    func addSecondUIView(aView: UIView, dispStr : String) {        
        //see above post!
    }
    
    
    func addSubviewButton(aView: UIView, return_msg: String, action_fcn : Selector) {
        //see above post!
    }
    
    
    func press_launch(sender: UIButton!) {
        //see above post!
    }
    
    
    func press_return(sender: UIButton!) {
        //see above post!
    }
    
    override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning(); }
    

    }