Snapchat-like swipe navigation between views in Xcode 6 and Swift)

前端 未结 7 620
清酒与你
清酒与你 2021-01-30 11:47

I\'ve been trying to implement swipe navigation between View Controllers in my app using the Swipe Gesture Recognizer and embeded Navigation Controller, but it doesn\'t look eve

相关标签:
7条回答
  • 2021-01-30 12:17

    I suggest using UIPageViewController and hiding the dots bar by deleting these methods:

    presentationCountForPageViewController
    presentationIndexForPageViewController
    

    Here is a good tutorial:

    https://www.youtube.com/watch?v=8bltsDG2ENQ

    Here is a great repo for this:

    https://github.com/goktugyil/EZSwipeController

    0 讨论(0)
  • 2021-01-30 12:19

    You need a pageviewcontroller. This was originally for showing tutorials and stuff but you can put view controllers in there as well. There are tons of tutorials out there and essentially you have to apply a little bit of logic to tell the program what view controller to show it next.

    This is a pretty advanced example, but it might be of help to you:

    https://github.com/cwRichardKim/RKSwipeBetweenViewControllers

    0 讨论(0)
  • 2021-01-30 12:28

    Paged Scroll View, not a PageViewController in the case of Snapchat.

    0 讨论(0)
  • 2021-01-30 12:29

    I'm not fond of the version given by lbrendanl because it does not use constraints. We can not custom it like we want. Here is the same version but with constraints :

    scrollView is an IBOutlet pined to the controller with 4 constraints with a constant to 0 at each sides to the controller's view.

    contentView is also an IBOutlet added as subview of scrollView pined to the scrollView with 4 constraints with a constant to 0 at each sides. It also has an equal height constraint and a width equal constraint. The width equal constraint is removed at runtime and only serves to calm down IB. This view represents the contentView of the scrollView.

    UPDATE iOS 9

     func setupDetailViewControllers() {
        var previousController: UIViewController?
        for controller in self.controllers {
            addChildViewController(controller)
            addControllerInContentView(controller, previousController: previousController)
            controller.didMoveToParentViewController(self)
            previousController = controller
        }
    }
    
    func addControllerInContentView(controller: UIViewController, previousController: UIViewController?) {
        contentView.addSubview(controller.view)
        controller.view.translatesAutoresizingMaskIntoConstraints = false
    
        // top
        controller.view.topAnchor.constraintEqualToAnchor(contentView.topAnchor).active = true
    
        // bottom
        controller.view.bottomAnchor.constraintEqualToAnchor(contentView.bottomAnchor).active = true
    
        // trailing
        trailingContentViewConstraint?.active = false
        trailingContentViewConstraint = controller.view.trailingAnchor.constraintEqualToAnchor(contentView.trailingAnchor)
        trailingContentViewConstraint?.active = true
    
        // leading
        let leadingAnchor = previousController?.view.trailingAnchor ?? contentView.leadingAnchor
        controller.view.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true
    
        // width
        controller.view.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
    }
    

    PREVIOUS ANSWER

        class ContainerViewController: UIViewController {
    
        @IBOutlet var scrollView: UIScrollView!
        @IBOutlet var contentView: UIView!
    
        // A strong reference to the width contraint of the contentView
        var contentViewConstraint: NSLayoutConstraint!
    
        // A computed version of this reference
        var computedContentViewConstraint: NSLayoutConstraint {
            return NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: .Width, multiplier: CGFloat(controllers.count + 1), constant: 0)
        }
    
        // The list of controllers currently present in the scrollView
        var controllers = [UIViewController]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            initScrollView()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
    
        }
    
        func initScrollView(){
            contentView.setTranslatesAutoresizingMaskIntoConstraints(false)
    
            contentViewConstraint = computedContentViewConstraint
            view.addConstraint(contentViewConstraint)
    
            // Adding all the controllers you want in the scrollView
            let controller1 = storyboard!.instantiateViewControllerWithIdentifier("AStoryboardID") as! AnUIControllerViewSubclass
            addToScrollViewNewController(controller)
            let controller2 = storyboard!.instantiateViewControllerWithIdentifier("AnotherStoryboardID") as! AnotherUIControllerViewSubclass
            addToScrollViewNewController(controller2)
        }
    
        // The main method, adds the controller in the scrollView at the left of the previous controller added
        func addToScrollViewNewController(controller: UIViewController) {
            self.addChildViewController(controller)
    
            contentView.addSubview(controller.view)
    
            controller.view.setTranslatesAutoresizingMaskIntoConstraints(false)
    
            // Setting all the constraints 
            let bottomConstraint = NSLayoutConstraint(item: contentView, attribute: .Bottom, relatedBy: .Equal, toItem: controller.view, attribute: .Bottom, multiplier: 1.0, constant: 0)
    
            let topConstraint = NSLayoutConstraint(item: contentView, attribute: .Top, relatedBy: .Equal, toItem: controller.view, attribute: .Top, multiplier: 1.0, constant: 0)
    
            let widthConstraint = NSLayoutConstraint(item: controller.view, attribute: .Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0)
    
            var trailingConstraint: NSLayoutConstraint!
            if controllers.isEmpty {
                // Since it's the first one, the trailing constraint is from the controller view to the contentView
                trailingConstraint = NSLayoutConstraint(item: contentView, attribute: .Trailing, relatedBy: .Equal, toItem: controller.view, attribute: .Trailing, multiplier: 1.0, constant: 0)
            }
            else {
                trailingConstraint = NSLayoutConstraint(item: controllers.last!.view, attribute: .Leading, relatedBy: .Equal, toItem: controller.view, attribute: .Trailing, multiplier: 1.0, constant: 0)
            }
    
            // Setting the new width constraint of the contentView
            view.removeConstraint(contentViewConstraint)
            contentViewConstraint = computedContentViewConstraint
    
            // Adding all the constraints to the view hierarchy
            view.addConstraint(contentViewConstraint)
            contentView.addConstraints([bottomConstraint, topConstraint, trailingConstraint])
            scrollView.addConstraints([widthConstraint])
    
            controller.didMoveToParentViewController(self)
    
            // Finally adding the controller in the list of controllers
            controllers.append(controller)
        }  
    }
    

    I've used the lbrendanl's version in the past. Now I prefer this one. Let me know what you think of it.

    0 讨论(0)
  • 2021-01-30 12:29

    I had similar requirement, initially implemented with PageController, but later I've changed it to UICollectionView where each cell is fullscreen and scroll is set to horizontal.

    0 讨论(0)
  • 2021-01-30 12:38

    The short version is to use a container view controller with a scrollview inside the controller. You then create separate view controllers for each screen you want in the application, and make those view controllers' parent the container view controller.

    A github repo with sample code can be found, here.

    0 讨论(0)
提交回复
热议问题