web-dev-qa-db-fra.com

iOS Segue - De gauche à droite -

J'ai lu les autres articles sur Segues mais aucun n'a résolu ma question. 

En termes simples, mes ViewControllers 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 ViewControllers 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.

  1. 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.

  2. 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.

  3. Codage en Swift. 

  4. 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.

This error is returned when I insert DCDC's code into an IBAction for my back-swipe

37
Dave G

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".

81
Michael Hudson

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.

41
rambossa

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)
            }
        )
    }
}
11
Mark Barrasso

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

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/

4
DCDC

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. 

2
Richard Venable

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)
1
Ashwin Felix

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é ...

1
Thialyson Martins

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".

0
MRizwan33

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)
    }
}
0
Felecia Genet

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

0
aestusLabs