169 votes

Est-il possible de tourner la page de manière programmée dans UIPageViewController ?

Est-il possible de tourner la page de manière programmable dans UIPageViewController ?

0 votes

Entièrement expliqué ici : stackoverflow.com/a/26024779/294884 Remarquez la "version du contour la plus simple"

0 votes

Ceci a radicalement changé en dix ans, faites défiler jusqu'à "Solution la plus simple 2022"

252voto

samwize Points 4144

Oui, c'est possible avec la méthode :

- (void)setViewControllers:(NSArray *)viewControllers 
                 direction:(UIPageViewControllerNavigationDirection)direction 
                  animated:(BOOL)animated 
                completion:(void (^)(BOOL finished))completion;`

C'est la même méthode utilisée pour configurer le premier contrôleur de vue sur la page. De manière similaire, vous pouvez l'utiliser pour accéder à d'autres pages.

Vous vous demandez pourquoi viewControllers est un tableau, et non un seul contrôleur de vue ?

C'est parce qu'un contrôleur de page peut avoir une "colonne vertébrale" (comme dans iBooks), affichant 2 pages de contenu à la fois. Si vous n'affichez qu'une page de contenu à la fois, passez simplement un tableau à un élément.

Un exemple en Swift :

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)

2 votes

Maintenant que l'NDA est levé, peut-on en dire un peu plus à ce sujet ? Peut-être un exemple de code.

12 votes

Je pense que j'ai enfin compris : UIPageViewController ne se soucie pas vraiment de la page sur laquelle il se trouve actuellement. Lorsque vous appelez setViewControllers, il peut donner l'impression que vous naviguez de façon animée loin du contrôleur de vue actuel, mais il ne cherche pas vraiment à aller sur une page.

3 votes

[self setViewControllers:@[vcToMoveTo] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; // où vcToMoveTo est un UIViewController

37voto

Joe Points 261

Comme j'avais également besoin de cela, je vais entrer dans plus de détails sur la façon de le faire.

Remarque : Je suppose que vous avez utilisé le formulaire de modèle standard pour générer la structure de votre UIPageViewController - qui crée à la fois le modelViewController et le dataViewController lorsque vous l'invoquez. Si vous ne comprenez pas ce que j'ai écrit - revenez en arrière et créez un nouveau projet qui utilise le UIPageViewController comme base. Vous comprendrez alors.

Donc, pour avoir besoin de basculer vers une page particulière, il faut configurer les différentes parties de la méthode énumérée ci-dessus. Pour cet exercice, je suppose qu'il s'agit d'une vue en paysage avec deux vues affichées. De plus, j'ai implémenté ceci en tant qu'IBAction afin qu'il puisse être fait à partir d'une pression sur un bouton ou autre - il est tout aussi facile de le faire en tant qu'appel de sélecteur et de passer les éléments nécessaires.

Pour cet exemple, vous avez besoin des deux contrôleurs de vue qui seront affichés - et éventuellement, que vous avanciez dans le livre ou reculiez.

Remarquez que j'ai simplement codé en dur où aller aux pages 4 et 5 et j'utilise une avance rapide. À partir de là, vous pouvez voir que tout ce que vous avez à faire est de passer les variables qui vous aideront à obtenir ces éléments...

-(IBAction) flipToPage:(id)sender {

    // Récupérer les viewControllers aux positions 4 et 5 - notez, votre modèle est responsable de les fournir.
    // Techniquement, vous pourriez les avoir préfabriqués et les passer en tant qu'array contenant les deux éléments...

    DataViewController *premierViewController = [self.modelController viewControllerAtIndex:4 storyboard:self.storyboard];
    DataViewController *deuxiemeViewController = [self.modelController viewControllerAtIndex:5 storyboard:self.storyboard];

    // Mettez en place l'array qui contient ces gars...

    NSArray *viewControllers = nil;

    viewControllers = [NSArray arrayWithObjects:premierViewController, deuxiemeViewController, nil];

    // Maintenant, dites au pageViewContoller d'accepter ces gars et de tourner la page vers l'avant.
    // Encore une fois, l'avant est subjectif - vous pourriez aller en arrière. L'animation est facultative mais c'est
    // un bel effet pour votre public.

      [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

    // Voilà - c'est fini !

}

2 votes

J'ai la même exigence de passer à une page spécifique. Mais le code ci-dessus ne semble pas fonctionner pour moi. Qu'est-ce que je fais mal? J'ai 19 pages.

0 votes

Pouvons-nous utiliser ce fragment de code également lorsque nous fournissons les contrôleurs de vue via un objet source de données ?

21 votes

Quelle classe très mal mise en œuvre de manière bizarre, Apple.

31voto

lekksi Points 606

Voici un autre exemple de code pour une vue sur une seule page. L'implémentation de viewControllerAtIndex est omise ici, elle devrait renvoyer le contrôleur de vue correct pour l'index donné.

- (void)changePage:(UIPageViewControllerNavigationDirection)direction {
    NSUInteger pageIndex = ((FooViewController *) [_pageViewController.viewControllers objectAtIndex:0]).pageIndex;

    if (direction == UIPageViewControllerNavigationDirectionForward) {
        pageIndex++;
    }
    else {
        pageIndex--;
    }

    FooViewController *viewController = [self viewControllerAtIndex:pageIndex];

    if (viewController == nil) {
        return;
    }

    [_pageViewController setViewControllers:@[viewController]
                                  direction:direction
                                   animated:YES
                                 completion:nil];
}

Les pages peuvent être changées en appelant

[self changePage:UIPageViewControllerNavigationDirectionReverse];
[self changePage:UIPageViewControllerNavigationDirectionForward];

0 votes

Mais le contrôle de la page d'index ne se met pas à jour. Comment puis-je faire cela ?

1 votes

Cette réponse fonctionne pour moi - notez cependant que si vous vous fiez aux méthodes de délégué "didFinishAnimating" de UIPageViewController, elles ne seront pas déclenchées. Au lieu de cela, déplacez votre code de didFinishAnimating dans une méthode séparée et appelez cette méthode depuis le bloc de complétion sur la méthode setViewControllers.

1 votes

@thatzprem Si vous souhaitez continuer à utiliser UIPageControl, alors vous voudrez peut-être : self.currentIndex = index de viewControllerToMoveTo puis pour presentationIndexForPageViewController retournez self.currentIndex

15voto

Graham Points 121

Ce code a bien fonctionné pour moi, merci.

Voici ce que j'en ai fait. Quelques méthodes pour avancer ou reculer et une pour aller directement à une page particulière. C'est pour un document de 6 pages en mode portrait. Cela fonctionnera bien si vous le collez dans l'implémentation du RootController du modèle de pageViewController.

-(IBAction) pageGoto: (id) sender {

    // obtenir la page à aller
    NSUInteger pageToGoTo = 4;

    // obtenir l'index actuel de la page actuelle
    DataViewController * theCurrentViewController = [self.pageViewController.viewControllers   objectAtIndex: 0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController: theCurrentViewController];

    // obtenir la ou les pages à aller
    DataViewController * targetPageViewController = [self.modelController viewControllerAtIndex: (pageToGoTo - 1) storyboard: self.storyboard];

    DataViewController * secondPageViewController = [self.modelController viewControllerAtIndex: (pageToGoTo) storyboard: self.storyboard];

    // mettre la ou les pages dans un tableau
    NSArray * theViewControllers = nil;    
    theViewControllers = [NSArray arrayWithObjects: targetPageViewController, secondPageViewController, nil];

    // vérifier dans quelle direction animer le changement de page puis tourner la page en conséquence
    if (retreivedIndex < (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){
        [self.pageViewController setViewControllers: theViewControllers direction: UIPageViewControllerNavigationDirectionForward animated: YES completion: NULL];
    }

    if (retreivedIndex > (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){
        [self.pageViewController setViewControllers: theViewControllers direction: UIPageViewControllerNavigationDirectionReverse animated: YES completion: NULL];
    }

}

-(IBAction) pageFoward: (id) sender {

    // obtenir l'index actuel de la page actuelle
    DataViewController * theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex: 0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController: theCurrentViewController];

    // vérifier que la page actuelle n'est pas la première page
    if (retreivedIndex < 5){

        // obtenir la page à aller
        DataViewController * targetPageViewController = [self.modelController viewControllerAtIndex: (retreivedIndex + 1) storyboard: self.storyboard];

        // mettre la ou les pages dans un tableau
        NSArray * theViewControllers = nil;    
        theViewControllers = [NSArray arrayWithObjects: targetPageViewController, nil];

        // ajouter la vue de la page
        [self.pageViewController setViewControllers: theViewControllers direction: UIPageViewControllerNavigationDirectionForward animated: YES completion: NULL];

    }

}

-(IBAction) pageBack: (id) sender {

    // obtenir l'index actuel de la page actuelle
    DataViewController * theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex: 0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController: theCurrentViewController];

    // vérifier que la page actuelle n'est pas la première page
    if (retreivedIndex > 0){

    // obtenir la page à aller
    DataViewController * targetPageViewController = [self.modelController viewControllerAtIndex: (retreivedIndex - 1) storyboard: self.storyboard];

    // mettre la ou les pages dans un tableau
    NSArray * theViewControllers = nil;    
    theViewControllers = [NSArray arrayWithObjects: targetPageViewController, nil];

    // ajouter la vue de la page
    [self.pageViewController setViewControllers: theViewControllers direction: UIPageViewControllerNavigationDirectionReverse animated: YES completion: NULL];

    }

}

0 votes

Je veux l'utiliser en mode paysage où deux pages existent. Comment l'utiliser là-bas? Pouvez-vous s'il vous plaît me guider?

3voto

noRema Points 378

Cependant, en utilisant cette méthode 'self.pageViewController setViewControllers' ne déclenche pas l'appel de 'viewDidDissapear' sur le viewController de la page qui a été tournée, alors que tourner une page manuellement déclenche bien 'viewDidDissapear' sur la page tournée. Je crois que c'est la cause de mon plantage

"Le nombre de contrôleurs de vue fournis (0) ne correspond pas au nombre requis (1) pour la transition demandée"

0 votes

Essayez d'utiliser : - pageViewController:didFinishAnimating:previousViewController‌s:transitionComplete‌d:

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X