J'ai essayé d'implémenter la navigation par balayage entre les contrôleurs de vue dans mon application à l'aide de la reconnaissance du geste de balayage et du contrôleur de navigation intégré, mais cela ne semble même pas proche de la navigation de Snapchat.
Quelle serait la manière la plus efficace et la plus appropriée de mettre en œuvre une telle fonctionnalité?
Je suis assez novice pour Swift et la programmation vraiment, et j'apprécierais tous les commentaires utiles.
La version courte consiste à utiliser un contrôleur de vue de conteneur avec une vue de défilement à l'intérieur du contrôleur. Vous créez ensuite des contrôleurs de vue distincts pour chaque écran de votre choix dans l'application, et vous faites du parent de ces contrôleurs de vue le contrôleur de vue du conteneur.
Un dépôt github avec un exemple de code peut être trouvé, ici .
Vous avez besoin d'un contrôleur de visualisation de page. C'était à l'origine pour montrer des tutoriels et d'autres choses, mais vous pouvez également y placer des contrôleurs de vue. Il existe des tonnes de tutoriels et vous devez essentiellement appliquer un peu de logique pour indiquer au programme quelle vue le contrôleur doit afficher ensuite.
Ceci est un exemple assez avancé, mais il pourrait vous être utile:
https://github.com/cwRichardKim/RKSwipeBetweenViewControllers
Je n'aime pas la version donnée par lbrendanl car elle n'utilise pas de contraintes. Nous ne pouvons pas le personnaliser comme nous le voulons. Voici la même version mais avec des contraintes:
scrollView est une IBOutlet attachée au contrôleur avec 4 contraintes avec une constante à 0 de chaque côté à la vue du contrôleur.
contentView est également un IBOutlet ajouté en tant que sous-vue de scrollView épinglé à scrollView avec 4 contraintes avec une constante à 0 de chaque côté. Il a également une contrainte de hauteur égale et une contrainte de largeur égale. La contrainte d'égalité de largeur est supprimée lors de l'exécution et ne sert qu'à calmer IB. Cette vue représente le contentView du scrollView.
METTRE À JOUR 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
}
RÉPONSE PRÉCÉDENTE
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)
}
}
J'ai utilisé la version de lbrendanl dans le passé. Maintenant, je préfère celui-ci. Faites-moi savoir ce que vous en pensez.
Je suggère d'utiliser UIPageViewController et de masquer la barre de points en supprimant ces méthodes:
presentationCountForPageViewController
presentationIndexForPageViewController
Voici un bon tutoriel:
https://www.youtube.com/watch?v=8bltsDG2ENQ
Voici un excellent repo pour cela:
J'avais une exigence similaire, initialement implémentée avec PageController
, mais plus tard, je l'ai changé en UICollectionView
où chaque cellule est en plein écran et le défilement est défini sur horizontal.
Vue de défilement paginée, pas un PageViewController dans le cas de Snapchat.
Vous pouvez essayer d'utiliser CATransition
pour créer l'animation de balayage. Voici un exemple de la façon dont vous pouvez passer d'une vue à une autre:
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"];
J'ai trouvé une partie de ce code ici: Comment puis-je implémenter une animation de balayage/glissement entre les vues?