Snapchat-подобная навигационная перемотка между представлениями в Xcode 6 и Swift)

Я пытаюсь реализовать навигацию по навигации между контроллерами View в моем приложении с помощью Sweep Gesture Recognizer и встроенного навигационного контроллера, но он не выглядит даже близко к навигатору Snapchat.

Каким будет наиболее эффективный и подходящий способ реализации таких функций?

Я новичок в Swift и программирую на самом деле, и я был бы признателен за каждый полезный комментарий.

Ответы

Ответ 1

Краткая версия - использовать контроллер представления контейнера со списком прокрутки внутри контроллера. Затем вы создаете отдельные контроллеры представлений для каждого экрана, который вы хотите использовать в приложении, и создавайте родительский элемент контроллера представления для контроллера контейнера.

Здесь можно найти репозиторий github с образцом кода, здесь.

Ответ 2

Вам нужен диспетчер просмотра страницы. Это изначально предназначалось для показа учебных пособий и других материалов, но вы также можете установить контроллеры представлений. Там есть множество учебных пособий, и, по сути, вам нужно применить немного логики, чтобы рассказать программе, какой контроллер просмотра должен показать ее дальше.

Это довольно продвинутый пример, но он может вам помочь:

https://github.com/cwRichardKim/RKSwipeBetweenViewControllers

Ответ 3

Я не люблю версию, данную lbrendanl, потому что она не использует ограничения. Мы не можем настраивать его так, как хотим. Вот такая же версия, но с ограничениями:

scrollView - это IBOutlet, спрятанный контроллером с 4 ограничениями с постоянной до 0 с каждой стороны до вида контроллера.

contentView также является IBOutlet, добавленным как subview scrollView, вычисленным в scrollView с четырьмя ограничениями с константой до 0 с каждой стороны. Он также имеет равное ограничение по высоте и ограничение по ширине. Ограничение ширины равно удаляется во время выполнения и служит только для успокоения IB. Это представление представляет contentView прокрутки.

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
}

ПРЕДЫДУЩИЙ ОТВЕТ

    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 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)
    }  
}

Я использовал версию lbrendanl в прошлом. Теперь я предпочитаю этот. Дайте мне знать, что вы думаете об этом.

Ответ 5

Paged Scroll View, а не PageViewController в случае Snapchat.

Ответ 6

Вы можете попробовать использовать CATransition для создания анимации прокрутки. Вот пример того, как вы можете переходить от одного вида к другому:

    UIView *parentView = [self.view superview];

CATransition *animation = [CATransition animation];
[animation setDuration:0.25];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

[parentView addSubview:yourSecondViewController.view];
[self.view removeFromSuperview];

[[theParentView layer] addAnimation:animation forKey:@"showSecondViewController"];

Я нашел здесь какой-то код: Как реализовать анимацию разворота/скольжения между представлениями?

Ответ 7

У меня было аналогичное требование, первоначально реализованное с помощью PageController, но позже я изменил его на UICollectionView, где каждая ячейка полноэкранная, а прокрутка - горизонтальная.