É possível virar a página programaticamente no UIPageViewController?

161

É possível virar a página programaticamente UIPageViewController?

RAGOpoR
fonte
1
você pode postar qualquer código de exemplo para ele. Grato a você.
iPhone programaticamente

Respostas:

235

Sim, é possível com o método:

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

Esse é o mesmo método usado para configurar o primeiro controlador de exibição na página. Similar, você pode usá-lo para acessar outras páginas.

Gostaria de saber por que viewControllersé uma matriz, e não um único controlador de exibição?

Isso ocorre porque um controlador de exibição de página pode ter uma "espinha" (como no iBooks), exibindo 2 páginas de conteúdo por vez. Se você exibir 1 página de conteúdo de cada vez, basta passar em uma matriz de 1 elemento.

Um exemplo no Swift:

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)
samwize
fonte
2
Agora que o NDA está ativo, isso pode ser expandido um pouco mais? Talvez um exemplo de código.
SpaceTrucker 1/11/11
11
Acho que finalmente entendi o seguinte: o UIPageViewController realmente não se importa com a página em que está atualmente. Quando você chama setViewControllers, pode parecer que você está navegando animadamente para longe do controlador de exibição atual, mas não está realmente procurando uma página.
Amy
3
exemplo: [auto setViewControllers: @ [vcToMoveTo] direction: UIPageViewControllerNavigationDirectionForward animado: conclusão SIM: nula]; // onde vcToMoveTo é um UIViewController
finneycanhelp
1
Se você quiser continuar usando o UIPageControl, poderá: self.currentIndex = viewControllerToMoveTo's index e, em seguida, para presentationIndexForPageViewController return self.currentIndex
brendan
3
Verifique stackoverflow.com/questions/22554877/… se também precisar atualizar a exibição do indicador de página
Protongun
37

Como eu também precisava disso, vou entrar em mais detalhes sobre como fazer isso.

Nota: Suponho que você tenha usado o formulário de modelo padrão para gerar sua UIPageViewControllerestrutura - que possui o modelViewControllere dataViewControllercriado quando você o invoca. Se você não entender o que escrevi - volte e crie um novo projeto que use oUIPageViewController base. Você entenderá então.

Portanto, a necessidade de acessar uma página específica envolve a configuração das várias partes do método listado acima. Para este exercício, suponho que seja uma visualização em paisagem com duas exibições em exibição. Além disso, eu implementei isso como uma IBAction para que isso pudesse ser feito com o pressionar de um botão ou não - é tão fácil fazer com que o seletor seja chamado e repassar os itens necessários.

Portanto, neste exemplo, você precisa dos dois controladores de exibição que serão exibidos - e, opcionalmente, se estiver avançando no livro ou para trás.

Observe que eu apenas codifiquei para onde ir para as páginas 4 e 5 e use um deslizamento para a frente. A partir daqui, você pode ver que tudo que você precisa fazer é passar as variáveis ​​que o ajudarão a obter esses itens ...

-(IBAction) flipToPage:(id)sender {

    // Grab the viewControllers at position 4 & 5 - note, your model is responsible for providing these.  
    // Technically, you could have them pre-made and passed in as an array containing the two items...

    DataViewController *firstViewController = [self.modelController viewControllerAtIndex:4 storyboard:self.storyboard];
    DataViewController *secondViewController = [self.modelController viewControllerAtIndex:5 storyboard:self.storyboard];

    //  Set up the array that holds these guys...

    NSArray *viewControllers = nil;

    viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, nil];

    //  Now, tell the pageViewContoller to accept these guys and do the forward turn of the page.
    //  Again, forward is subjective - you could go backward.  Animation is optional but it's 
    //  a nice effect for your audience.

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

    //  Voila' - c'est fin!  

}
Joe
fonte
2
Eu tenho o mesmo requisito para mudar para uma página específica. Mas o código acima parece não funcionar para mim. O que estou fazendo de errado? Eu tenho 19 páginas.
precisa saber é o seguinte
Podemos usar esse trecho de código também ao fornecer os controladores de exibição por meio de um objeto de fonte de dados?
Jens Kohl
20
Que classe bizarramente mal implementada, a Apple.
devios1
29

Aqui está outro exemplo de código para uma única exibição paginada. A implementação para viewControllerAtIndex é omitida aqui, ela deve retornar o controlador de exibição correto para o índice especificado.

- (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];
}

As páginas podem ser alteradas chamando

[self changePage:UIPageViewControllerNavigationDirectionReverse];
[self changePage:UIPageViewControllerNavigationDirectionForward];
lekksi
fonte
Mas o controle de índice da página não é atualizado. Como faço isso?
thatzprem
1
Esta resposta funciona para mim - observe, no entanto, que se você confiar nos métodos delegados "didFinishAnimating" do UIPageViewController, eles não serão acionados. Em vez disso, mova seu código de didFinishAnimating para um método separado e chame esse método do bloco de conclusão no método setViewControllers.
precisa saber é o seguinte
1
@thatzprem Se você quiser continuar usando o UIPageControl, poderá: self.currentIndex = índice do viewControllerToMoveTo e, em seguida, para presentationIndexForPageViewController retornar self.currentIndex
brendan
@thatzprem está certo. Toda vez que ele for para a mesma página, por exemplo, se tivermos 3 páginas, todas as vezes que ele for para a segunda página.
Tushar Lathiya
18

Eu poderia estar totalmente faltando alguma coisa aqui, mas esta solução parece muito mais simples do que muitas outras propostas.

extension UIPageViewController {
    func goToNextPage(animated: Bool = true, completion: ((Bool) -> Void)? = nil) {
        if let currentViewController = viewControllers?[0] {
            if let nextPage = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) {
                setViewControllers([nextPage], direction: .forward, animated: animated, completion: completion)
            }
        }
    }
}
wfbarksdale
fonte
1
Funciona bem! Só tenho que mudar o indicador da página de alguma forma.
TruMan1
Realmente util! Por favor, nos dê uma função para goToFirstPage também.
Mamta
Toda vez que ele for para a mesma página, por exemplo, se tivermos 3 páginas, todas as vezes que ele for para a segunda página.
Tushar Lathiya
15

Esse código funcionou bem para mim, obrigado.

Isto é o que eu fiz com isso. Alguns métodos para avançar ou retroceder e outro para ir diretamente para uma página específica. É para um documento de 6 páginas em modo retrato. Ele funcionará bem se você colá-lo na implementação do RootController do modelo pageViewController.

-(IBAction)pageGoto:(id)sender {

    //get page to go to
    NSUInteger pageToGoTo = 4;

    //get current index of current page
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers   objectAtIndex:0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];

    //get the page(s) to go to
    DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo - 1) storyboard:self.storyboard];

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

    //put it(or them if in landscape view) in an array
    NSArray *theViewControllers = nil;    
    theViewControllers = [NSArray arrayWithObjects:targetPageViewController, secondPageViewController, nil];


    //check which direction to animate page turn then turn page accordingly
    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 {

    //get current index of current page
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];

    //check that current page isn't first page
    if (retreivedIndex < 5){

        //get the page to go to
        DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex + 1) storyboard:self.storyboard];

        //put it(or them if in landscape view) in an array
        NSArray *theViewControllers = nil;    
        theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil];

        //add page view
        [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

    }

}


-(IBAction)pageBack:(id)sender {


    //get current index of current page
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];

    //check that current page isn't first page
    if (retreivedIndex > 0){

    //get the page to go to
    DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex - 1) storyboard:self.storyboard];

    //put it(or them if in landscape view) in an array
    NSArray *theViewControllers = nil;    
    theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil];

    //add page view
    [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL];

    }

}
Graham
fonte
Eu quero usá-lo para o modo paisagem, onde existem duas páginas. como usá-lo lá. você pode por favor orientar.
iPhone programaticamente
9

Swift 4:

Eu precisava ir para o próximo controlador ao tocar em um controlador de exibição de controlador de página e também atualizar o índice pageControl, portanto, essa foi a solução melhor e mais direta para mim :

let pageController = self.parent as! PageViewController

pageController.setViewControllers([parentVC.orderedViewControllers[1]], direction: .forward, animated: true, completion: nil)

pageController.pageControl.currentPage = 1
Sam Bing
fonte
5

Que tal usar métodos do dataSource?

UIViewController *controller = [pageViewController.dataSource pageViewController:self.pageViewController viewControllerAfterViewController:pageViewController.viewControllers.firstObject];
[pageViewController setViewControllers:@[controller] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

Analogicamente para trás.

JakubKnejzlik
fonte
3

Em Swift :

import UIKit

extension HomeViewController {

    // MARK: - Carousel management.

    func startTimerForMovingCarousel(let numberOfSecondsBetweenFiringsOfTheTimer: NSTimeInterval) {
        if (self.timerForMovingCarousel == nil) {
            self.timerForMovingCarousel = NSTimer.scheduledTimerWithTimeInterval(numberOfSecondsBetweenFiringsOfTheTimer,
                                                                            target: self,
                                                                            selector: "moveCarousel",
                                                                            userInfo: nil,
                                                                            repeats: true)
        }
    }

    func moveCarousel() {
        println("I move the carousel.")

        let currentContentViewControllerDisplayed = self.pageViewController!.viewControllers[0] as! ContentViewController

        var index: Int = currentContentViewControllerDisplayed.index

        if index == self.arrayViewControllers.count - 1 {
            index = 0
        } else {
            ++index
        }

        let contentViewControllerToDisplay = self.arrayViewControllers[index] as! ContentViewController

        self.pageViewController.setViewControllers([contentViewControllerToDisplay],
                                                    direction: UIPageViewControllerNavigationDirection.Forward,
                                                    animated: true,
                                                    completion: nil)

        self.pageControl.currentPage = contentViewControllerToDisplay.index
    }

    func invalidateTimerForMovingCarousel() {
        if (self.timerForMovingCarousel != nil) {
            self.timerForMovingCarousel.invalidate()
            self.timerForMovingCarousel = nil
        }
    }

}
O rei da bruxaria
fonte
1
Você poderia me dar um exemplo completo disso? Porque estou fazendo algo assim. Como usar esta extensão com o meu código. Se desejar, posso enviar o código.
Saty 28/09
2

No entanto, o uso dessa chamada de método 'self.pageViewController setViewControllers' não chama 'viewDidDissapear' no viewController para a página que foi recusada, enquanto que virar uma página manualmente chama viewDidDissapear na página recusada. Eu acredito que esta é a causa do meu acidente

"O número de controladores de exibição fornecidos (0) não corresponde ao número necessário (1) para a transição solicitada"

noRema
fonte
tente usar: - pageViewController: didFinishAnimating: previousViewControllers: transiçãoCompleted:
Graham
2

Eu também precisava de um botão para navegar para a esquerda em um PageViewController, que deveria fazer exatamente o que você esperaria do movimento do furto.

Como eu já tinha algumas regras em vigor dentro de " pageViewController: viewControllerBeforeViewController " para lidar com a navegação de furto natural, eu queria que o botão reutilizasse todo esse código e simplesmente não podia usar índices específicos para acessar páginas como as anteriores respostas fizeram. Então, eu tive que tomar uma solução alternativa.

Observe que o código a seguir é para um Page View Controller que é uma propriedade dentro do meu ViewController personalizado e tem sua coluna definida como média.

Aqui está o código que escrevi para o meu botão Navegar para a esquerda:

- (IBAction)btnNavigateLeft_Click:(id)sender {

    // Calling the PageViewController to obtain the current left page
    UIViewController *currentLeftPage = [_pageController.viewControllers objectAtIndex:0];

    // Creating future pages to be displayed
    NSArray *newDisplayedPages = nil;
    UIViewController *newRightPage = nil;
    UIViewController *newLeftPage = nil;

    // Calling the delegate to obtain previous pages
    // My "pageViewController:viewControllerBeforeViewController" method returns nil if there is no such page (first page of the book).
    newRightPage = [self pageViewController:_pageController viewControllerBeforeViewController:currentLeftPage];
    if (newRightPage) {
        newLeftPage = [self pageViewController:_pageController viewControllerBeforeViewController:newRightPage];
    }

    if (newLeftPage) {
        newDisplayedPages = [[NSArray alloc] initWithObjects:newLeftPage, newRightPage, nil];
    }

    // If there are two new pages to display, show them with animation.
    if (newDisplayedPages) {
        [_pageController setViewControllers:newDisplayedPages direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
    }
}

Você pode fazer algo muito semelhante para criar um botão de navegação correto a partir daqui.

tuliomir
fonte
2

Caso PAGE CONTROL para indicar a página atual seja O&& Você deseja que as páginas naveguem via rolagem e também clicando nos botões personalizados no Page ViewController, abaixo pode ser útil.

//Set Delegate & Data Source for PageView controller [Say in View Did Load]
   self.pageViewController.dataSource = self;
   self.pageViewController.delegate = self;

// Delegates called viewControllerBeforeViewController when User Scroll to previous page 

 - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{

    [_nextBtn setTitle:@"Next" forState:UIControlStateNormal];

    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

    if (index == NSNotFound){
        return nil;
    }else if (index > 0){
        index--;
    }else{
        return nil;
    }        
    return [self viewControllerAtIndex:index];        
}

// Delegar chamado viewControllerAfterViewController quando o Usuário Rolar para a próxima página

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{

    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

if (index == NSNotFound){
    return nil;
}else if (index < 3){
    index++;
}else{
    return nil;
}
return [self viewControllerAtIndex:index];}

//Delegate called while transition of pages. The need to apply logic in this delegate is to maintain the index of current page.

 - (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{ 

buttonIndex = (int)((PageContentViewController*) pendingViewControllers.firstObject).pageIndex;

}

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{    
if (buttonIndex == 0){
    _backButton.hidden = true;
}else if (buttonIndex == [self.pageImages count] - 1){
    _backButton.hidden = false;
    [_nextBtn setTitle:@"Begin" forState:UIControlStateNormal];
}else{
    _backButton.hidden = false;
}

}

// Lógica do botão personalizado (anterior e próximo)

-(void)backBtnClicked:(id)sender{
    if (buttonIndex > 0){
buttonIndex -= 1;
    }
    if (buttonIndex < 1) {
        _backButton.hidden = YES;
    }
    if (buttonIndex >=0) {
         [_nextBtn setTitle:@"Next" forState:UIControlStateNormal];
        PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex];
        NSArray *viewControllers = @[startingViewController];
        [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    }

}

-(void)nextBtnClicked:(id)sender{
if (buttonIndex < 3){
buttonIndex += 1;
}
if(buttonIndex == _pageImages.count){
   //Navigate Outside Pageview controller        
}else{        
    if (buttonIndex ==3) {

        [_nextBtn setTitle:@"Begin" forState:UIControlStateNormal];
    }
    _backButton.hidden = NO;

    PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}

}

//BUTTON INDEX & MAX COUNT
-(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{
    return [self.pageImages count];}

-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{
    return  buttonIndex;}
Yogesh Lolusare
fonte
Você postou a mesma resposta quase exata para quatro perguntas. Se você acha que um deles é uma duplicata do outro, marque-o como tal (e não publique a mesma resposta várias vezes).
28416 Jaap
Então, eu posso postar o link desta pergunta sobre outra pergunta semelhante, mas a solução é a mesma.
Yogesh Lolusare
1
Não pretendo julgar nem nada, mas sua formatação de código me parece muito desanimadora.
Lukas Petr
1
Certo @Lukas, vou formatá-lo agora. Obrigado
Yogesh Lolusare
2
- (void)moveToPage {

    NSUInteger pageIndex = ((ContentViewController *) [self.pageViewController.viewControllers objectAtIndex:0]).pageIndex;

    pageIndex++;

    ContentViewController *viewController = [self viewControllerAtIndex:pageIndex];

if (viewController == nil) {
        return;
    }
    [self.pageViewController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

}

// agora chame esse método

[self moveToPage];

Eu espero que dê certo :)

D.Garcia
fonte
1

Para uma página, acabei de editar a resposta de @Jack Humphries

-(void)viewDidLoad
{
  counter = 0;
}
-(IBAction)buttonClick:(id)sender
{
  counter++;
  DataViewController *secondVC = [self.modelController viewControllerAtIndex:counter storyboard:self.storyboard];
  NSArray *viewControllers = nil;          
  viewControllers = [NSArray arrayWithObjects:secondVC, nil];          
  [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
}
Smit Shah
fonte
0

Como o @samwize apontou, a maneira de paginar é usando

setViewControllers:array

Aqui está a maneira como eu fiz isso: tenho minha fonte de dados e o delegado separados. Você pode chamar esse método e alterar apenas a exibição "próxima". Anteriormente, você deve aplicar as regras de paginação. Ou seja, você deve verificar a direção e o próximo controlador. Se você usar esse método com sua fonte de dados personalizada, a matriz de controladores que você está exibindo não será alterada (já que você usará uma matriz personalizada em uma subclasse NSObject).

Usando sua própria fonte de dados, o método apenas define uma nova exibição (com direção específica). Como você ainda controlará as páginas que serão exibidas ao deslizar normalmente.

wolffan
fonte
0

Estou trabalhando nisso desde ontem e finalmente consegui. Não consegui usar totalmente o modelo padrão porque tenho três viewControllers diferentes como visões de filhos:

1 - rootViewController;
2 - model;
3 - viewControllers
3.1 - VC1;
3.2 - VC2;
3.3 - VC3.
Note: all of VCs has Storyboard ID.

Eu precisava de um botão de acionamento apenas no primeiro VC, então adicionei uma propriedade para pageViewController e model:

#import <UIKit/UIKit.h>
#import "Model.h"

@interface VC1 : UIViewController

@property (nonatomic, strong) UIPageViewController *thePageViewController;
@property (nonatomic, strong) SeuTimePagesModel *theModel;

@end

Reescrevi o método init do modelo para passar o storyboard e o pageViewController como parâmetros, para que eu pudesse defini-los no meu VC1:

- (id)initWithStoryboard:(UIStoryboard *)storyboard
   andPageViewController:(UIPageViewController *)controller
{
    if (self = [super init])
    {
        VC1 *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"VC1"];
        vc1.pageViewController = controller;
        vc1.model = self;

        VC2 *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"VC2"];
        VC3 *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"VC3"];
        self.pageData = [[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil];
    }

    return self;
}

Finalmente, adicionei uma IBAction no meu vc1 para acionar o método pageViewController setViewControllers: direction: animated: conclusão ::

- (IBAction)go:(id)sender
{
    VC2 *vc2 = [_model.pages objectAtIndex:1];
    NSArray *viewControllers = @[vc2];
    [_pageViewController setViewControllers:viewControllers
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:YES
                                 completion:nil];
}

Nota : não preciso encontrar índices de VCs, meu botão me leva ao meu segundo VC, mas não é difícil obter todos os índices e acompanhar suas visualizações de filhos:

- (IBAction)selecionaSeuTime:(id)sender
{
    NSUInteger index = [_model.pages indexOfObject:self];
    index++;

    VC2 *vc2 = [_model.pages objectAtIndex:1];
    NSArray *viewControllers = @[vc2];
    [_pageViewController setViewControllers:viewControllers
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:YES
                                 completion:nil];
}

Espero que ajude você!

Thomás Calmon
fonte
0

Aqui está uma solução usando os métodos UIPageViewControllerDataSource :

O código controla o atual controlador de exibição exibido no UIPageViewController .

...
@property (nonatomic, strong) UIViewController *currentViewController;
@property (nonatomic, strong) UIViewController *nextViewController;
...

Primeiro, inicialize currentViewController para o controlador de exibição inicial definido para o UIPageViewController .

- (void) viewDidLoad {
    [super viewDidLoad];
    ...
    self.currentViewController = self.viewControllers[0];
    ...
    [self.pageViewController setViewControllers: @[self.currentViewController] direction: dir animated: YES completion: nil];
}

Em seguida, manter o controle de currentViewController nas UIPageViewControllerDelegate métodos: pageViewController: willTransitionToViewControllers: e pageViewController: didFinishAnimating: previousViewControllers: transitionCompleted: .


- (nullable UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerBeforeViewController: (UIViewController *) viewController {
    NSInteger idx = [self.viewControllers indexOfObject: viewController];
    if (idx > 0) {
        return self.viewControllers[idx - 1];
    } else {
        return nil;
    }
}

- (nullable UIViewController *) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController: (UIViewController *) viewController {
    NSInteger idx = [self.viewControllers indexOfObject: viewController];
    if (idx == NSNotFound) {
        return nil;
    } else {
        if (idx + 1 < self.viewControllers.count) {
            return self.viewControllers[idx + 1];
        } else {
            return nil;
        }
    }
}

- (void) pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers {
    self.nextViewController = [pendingViewControllers firstObject];
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed {
    if (completed) {
        self.currentViewController = self.nextViewController;
    }
}

Finalmente, no método de sua escolha (no exemplo abaixo de - (IBAction) OnNext: (id) sender ), você pode programaticamente mudar para o controlador anterior ou seguinte utilizando UIPageViewControllerDataSouce métodos pageViewController: viewControllerBeforeViewController: , pageViewController: viewControllerAfterViewController: para obter o controlador de exibição seguinte ou anterior e navegue até ele chamando [self.pageViewController setViewControllers: @ [vc] direction: UIPageViewControllerNavigationDirectionForward animado: conclusão SIM: nula];


- (void) onNext {
    UIViewController *vc = [self pageViewController: self.tutorialViewController viewControllerAfterViewController: self.currentViewController];
    if (vc != nil) {
        self.currentViewController = vc;
        [self.tutorialViewController setViewControllers: @[vc] direction: UIPageViewControllerNavigationDirectionForward animated: YES completion: nil];
    }
}
pconor
fonte
Uma explicação detalhada teria sido muito útil.
Taslim Oseni
@TlimlimOseni, obrigado por apontar que o exemplo não estava claro o suficiente. Adicionei uma descrição de como funciona. Entre em contato se precisar de mais explicações.
Pconor
0

Como os ViewControllers são incorporados no PageViewController, tudo o que você precisa fazer é:

  • Recupere o controlador de exibição dos pais e faça o elenco como sua classe relevante.
  • Use a propriedade da fonte de dados pais para obter o próximo ViewController.
  • Use o método SetParentViewControllers para definir e fazer a transição para a próxima página.

Exemplo no Xamarin, mas funcionalmente semelhante ao Swift etc. O código a seguir estaria no botão Clique em delegar em um dos ViewControllers que são mostrados como uma página:

var parent = ParentViewController as WelcomePageViewController;
var next = parent.DataSource.GetNextViewController(parent, this);

parent.SetViewControllers(new UIViewController[] { next }, UIPageViewControllerNavigationDirection.Forward, true, null);
Grant K
fonte