J'ai lu les autres articles sur Segues mais aucun n'a résolu ma question.
En termes simples, mes ViewController
s sont commandés, comme un livre. Je veux que les transitions en arrière (exemple: de la page 9 à la page 8) soient toujours présentées (glissent dessus) de gauche à droite. Je souhaite que les transitions avant (pages 9 à 10) soient présentées de droite à gauche.
Oui, le bouton de retour de mon contrôleur de navigation (en haut à gauche) se présente de la même manière si vous parcourez page par page. Cependant, si vous sautez depuis un index, la fonction de retour du contrôleur de navigation vous ramène à l’index.
Mon objectif est que si un utilisateur passe à la page 9 (par exemple) d'un index, puis balaie le curseur vers la droite, la page se déplace vers la droite et affiche la page 8. Une fois à la page 8, s'il passe à gauche, la page être déplacé vers la gauche et ils seront à la page 9 à nouveau.
Tous mes ViewController
s sont par défaut, présentant en glissant de droite à gauche.
Exemple: Pensez-y comme à un livre, si j'utilise l'index pour aller au chapitre 4, puis que vous balayez vers la droite et que vous sortez une vue de la pile, je reviens à l'index. Mais si vous êtes au Chapitre 4, page 394 et que vous glissez à droite, vous ne voulez pas revenir à l'index! Vous voulez aller à la dernière page du chapitre 3, page 393! Donc, la pile de navigation ne m'aide pas.
Exemple de fin
Détails: 1. J'utilise le nouveau "Afficher" Xcode sur un bouton pour basculer entre ViewControllers.
J'utilise un contrôleur de navigation, pour la fonctionnalité du bouton "Retour" en haut à gauche. Cela utilise la pile de navigation et fonctionne bien.
Cependant, j'ai ma propre barre de navigation personnalisée en bas (bouton Précédent, bouton Accueil, bouton Index, bouton Suivant) et des gestes. Ce sont ce que je veux avoir avec une fonctionnalité de livre comme.
Codage en Swift.
Travailler avec Xcode 6.3
J'ai lu qu'il y a du code d'animation. J'ai lu qu'il est possible d'utiliser des transitions programmatiques approfondies. Il semble simplement insensé qu’il n’existe aucun moyen simple de sélectionner les segments que je souhaite présenter à partir de la gauche et d’inverser facilement l’animation.
Merci!
Journal des tentatives:
I tried DCDC's code:
UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
self.window!.rootViewController = mainVC
}, completion:nil)
Cette erreur est renvoyée lorsque j'insère le code de DCDC dans une variable IBAction
pour mon balayage du dos.
C'est comme ça que je réalise l'effet sans avoir besoin d'un contrôleur de navigation. Essayez ceci à la place:
Swift 4:
import UIKit
class SegueFromLeft: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: .curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
}
)
}
}
Swift 3:
import UIKit
class SegueFromLeft: UIStoryboardSegue
{
override func perform()
{
let src = self.sourceViewController
let dst = self.destinationViewController
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0)
UIView.animateWithDuration(0.25,
delay: 0.0,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: {
dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
},
completion: { finished in
src.presentViewController(dst, animated: false, completion: nil)
}
)
}
}
Ensuite, dans le storyboard, cliquez sur la séquence que vous souhaitez modifier. Dans l'inspecteur d'attributs, changez le type en "Personnalisé" et la classe en "SegueFromLeft".
Voici une classe de séquence personnalisée que vous pouvez utiliser pour effectuer une séquence de gauche à droite dans Swift. Cela nécessite un framework QuartzCore et une animation minimale.
Swift 2.2
import UIKit
import QuartzCore
class SegueFromLeft: UIStoryboardSegue {
override func perform() {
let src: UIViewController = self.sourceViewController
let dst: UIViewController = self.destinationViewController
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.25
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
src.navigationController!.view.layer.addAnimation(transition, forKey: kCATransition)
src.navigationController!.pushViewController(dst, animated: false)
}
}
Swift 3.0
import UIKit
import QuartzCore
class SegueFromLeft: UIStoryboardSegue {
override func perform() {
let src: UIViewController = self.source
let dst: UIViewController = self.destination
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.25
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
src.navigationController!.view.layer.add(transition, forKey: kCATransition)
src.navigationController!.pushViewController(dst, animated: false)
}
}
Le bouton "Retour" apparaîtra toujours dans la barre de navigation du contrôleur de vue en transition, mais vous pouvez facilement désactiver/configurer le contrôleur de navigation pour ce contrôleur de vue.
Mise à jour de la réponse acceptée dans Swift 3:
import UIKit
class SegueFromLeft: UIStoryboardSegue
{
override func perform()
{
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIViewAnimationOptions.curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
}
)
}
}
Réponse acceptée mis à jour pour Swift 3 (à partir de juin 2017)
Passer de de gauche à droite
import UIKit
class SegueFromLeft: UIStoryboardSegue {
override func perform() {
let src = self.source //new enum
let dst = self.destination //new enum
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0) //Method call changed
UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
}) { (finished) in
src.present(dst, animated: false, completion: nil) //Method call changed
}
}
}
Passer de de droite à gauche
import UIKit
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width*2, y: 0) //Double the X-Axis
UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
}) { (finished) in
src.present(dst, animated: false, completion: nil)
}
}
}
Vous pouvez utiliser le type de déclaration prédéfini dans la méthode transitionWithView
UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
self.window!.rootViewController = mainVC
}, completion:nil)
Je suppose que .TransitionFlipFromLeft est celui désiré
Pour terminer la tâche, faites glisser un nouveau contrôleur de vue sur votre story-board et nommez-le avec un identifiant. Ce sera la destination de la transition.
puis instancier ce contrôleur de vue à partir du code
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let mainVC = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController
Vous pouvez le faire soit dans IBAction, soit par exemple dans ViewDidLoad, mais il est probable qu'IBAction sera le meilleur choix. Faites attention à saisir les identifiants corrects pour le storyboard et le contrôleur de vue. En outre, vous devez déclarer votre instance appDelegate. Voici l'IBAction implémenté
@IBAction func Push(sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainVC = storyboard.instantiateViewControllerWithIdentifier("secondVC") as! UIViewController
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
UIView.transitionWithView(appDelegate.window!, duration: 0.5, options: .TransitionFlipFromLeft , animations: { () -> Void in
appDelegate.window!.rootViewController = mainVC
}, completion:nil)
}
Si ce n'est pas ce que vous attendiez, vous voudrez probablement créer une animation personnalisée. Cet article est vraiment utile: http://mathewsanders.com/animated-transitions-in-Swift/
On dirait que vous essayez simplement d'extraire un contrôleur de vue de la pile de UINavigationController, comme le ferait le bouton Précédent par défaut.
Vous pouvez faire l'une des deux choses. Le plus simple est de connecter votre bouton Précédent personnalisé à un IBAction qui appelle popViewControllerAnimated ():
@IBAction func tappedCustomBackButton(sender: AnyObject) {
self.navigationController?.popViewControllerAnimated(true)
}
Ou vous pouvez créer un dérouler le passage de votre deuxième contrôleur de vue à votre premier.
Seguer à partir de la droite. Vous pouvez remplacer la fonction performer en segue comme ci-dessous. placez cette fonction dans une classe de séquence personnalisée et affectez cette classe à la division . elle fonctionnera pour les deux contrôleurs avec contrôleur de navigation et sans contrôleur de navigation.
override func perform()
{
let src = self.sourceViewController
print(src)
let dst = self.destinationViewController
print(dst)
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.height, 0)
UIView.animateWithDuration(0.35,
delay: 0.0,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: {
dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
},
completion: { finished in
if let navController = src.navigationController {
navController.pushViewController(dst, animated: false)
} else {
src.presentViewController(dst, animated: false, completion: nil)
} }
)
}
si vous voulez la transition de gauche alors utilisez cette
CGAffineTransformMakeTranslation(-src.view.frame.size.height, 0)
Dans mon cas, je faisais un menu dans la barre latérale ...
J'ai créé un nouveau contrôleur de vue et deux divisions de douane
POUR OUVRIR LE MENU:
import Foundation
import UIKit
class SegueFromLeft: UIStoryboardSegue {
override func perform() {
let src = self.source as UIViewController
let dst = self.destination as UIViewController
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIViewAnimationOptions.curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
}
)
}
}
POUR FERMER LE MENU:
import Foundation
import UIKit
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source as UIViewController
let dst = self.destination as UIViewController
src.view.superview?.insertSubview(dst.view, belowSubview: src.view)
src.view.transform = CGAffineTransform(translationX: 0, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIViewAnimationOptions.curveEaseInOut,
animations: {
src.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
},
completion: { finished in
src.dismiss(animated: false, completion: nil)
}
)
}
}
J'espère que cela vous a aidé ...
Hé mec, j'ai la solution complète il suffit de copier et coller ce code écrit Swift 3.
func menu(){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MyAccountViewController") as! MyAccountViewController
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.5
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
self.navigationController?.view.layer.add(transition, forKey: kCATransition)
self.navigationController?.pushViewController(vc, animated: false)
}
Remarque: modifiez le nom de votre ViewController avec le texte "MyAccountViewController".
Pour créer un "bouton Précédent" comme une animation, utilisez ceci.
class SegueRightToLeft: UIStoryboardSegue {
override func perform() {
let src = self.source //new enum
let dst = self.destination //new enum
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width/2, y: 0)
//slice the x axis translation in half
UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
}) { (finished) in
src.present(dst, animated: false, completion: nil)
}
}
Mise à jour de la réponse acceptée à Swift 4:
class SegueFromLeft: UIStoryboardSegue
{
override func perform(){
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIViewAnimationOptions.curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
})
}
}
N'hésitez pas à copier ceci dans la réponse acceptée et à supprimer ce commentaire. (C'est une mise à jour directe, rien de nouveau.)