Created
March 8, 2017 13:48
-
-
Save runys/6d1e41d8498222e880663bbc871b120d to your computer and use it in GitHub Desktop.
Tutorial about how to create a simple page view application in iOS 10 with Swift 3. Originally create to be seen in a playground.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*: | |
## Tutorial de UIPageViewController | |
Referências: | |
- [How to Use UIPageViewController in Swift 2.2](https://spin.atomicobject.com/2015/12/23/swift-uipageviewcontroller-tutorial/) | |
- [How to Move Page Dots in a UIPageViewController with Delegation](https://spin.atomicobject.com/2016/02/11/move-uipageviewcontroller-dots/) | |
- [](https://developer.apple.com/reference/uikit/uipageviewcontroller) | |
- [](https://developer.apple.com/reference/uikit/uipageviewcontrollerdatasource) | |
- [](https://developer.apple.com/reference/uikit/uipageviewcontrollerdelegate) | |
Olá amigos! Vamos aprender como utilizar Page View Controller para fazermos aquela tela bacana de tutorial. | |
1. Crie seu projeto um novo projeto no XCode, uma `Single View Application`. | |
Antes de partirmos pro código, temos que fazer umas coisinhas no `Main.storyboard` | |
### No `Main.storyboard`: | |
2. Apague a `ViewController` que já veio pronta pra você. | |
3. Adicione uma `Page View Controller` e a defina como tela inicial (`Is Initial View Controller`). | |
4. Na aba `Attributes` defina a propriedade `Transition Style` da Page View Controller como `Scroll` | |
5. Crie três `View Controller`s e pinte a `View` de cada uma com uma cor (Vermelho, Azul, Amarelo). | |
Muita atenção nestes próximos passos. Para cada `View Controller` que você criou, selecione-a e: | |
6. Vá no `Identity Inspector`. | |
7. Na seção `Identity` coloque o nome da cor no campo `Storyboard ID` (Vermelho, Azul, Amarelo). Lembre-se de apertar `enter`. | |
8. Marque o campo `Use Storyboard ID`. | |
### Classe TutorialPageViewController | |
Agora vamos ao código, shall we? | |
1. Crie um novo arquivo `Cocoa Touch Class`. | |
2. O `nome` da classe será `TutorialViewController`. | |
3. Ele será `subclass` de `UIPageViewController`. | |
4. Vá no `Main.storyboard` e selecione seu `Page View Controller`. | |
5. Com ele selecionado vá na seção `Identity` e defina a `class` como `TutorialViewController`. | |
*/ | |
import UIKit | |
class TutorialViewController: UIPageViewController { | |
// 1. Precisamos do nosso UIPageControl para mostrar em que página o usuário esta | |
var paginador = UIPageControl() | |
// 2. Vamos inserir nosso `paginador` na nossa `view` assim que ela for inicializado | |
func inicializarPaginador() { | |
// 3. Definimos o número de páginas (vamos criar esse array já já) | |
self.paginador.numberOfPages = self.tutorialViewControllers.count | |
// 4. Definimos a página inicial do paginador | |
self.paginador.currentPage = 0 | |
let meioDaTela = self.view.frame.width / 2 | |
let parteDeBaixoDaTela = self.view.frame.height - 16 | |
// 5. Posicionamos o paginador no centro e na parte de baixo da tela | |
self.paginador.frame.origin = CGPoint(x: meioDaTela, y: parteDeBaixoDaTela) | |
// 6. Adicionamos nosso paginador na nossa `view`, agora ele está aparecendo na tela | |
self.view.addSubview(self.paginador) | |
} | |
// 1. Precisamos agora de uma forma de pegar as View Controllers la no Storyboard. | |
// Este método faz exatamente isso! | |
// Você diz pra ele o identificador da View Controller e ele te traz ela para que você use :) | |
private func viewControllerChamada(_ identifier: String) -> UIViewController { | |
// Pegamos o Main.storyboard, é nele que vamos buscar nossas View Controllers | |
let storyboard = UIStoryboard(name: "Main", bundle: nil) | |
// Agora instanciamos a View Controller de acordo com o identificador dela | |
let vc = storyboard.instantiateViewController(withIdentifier: identifier) | |
return vc | |
} | |
// 1. Agora vamos definir as páginas do nosso tutorial, as View Controllers que irão aparecer para o usuário | |
// Esta é uma propriedade `lazy`, ou seja, só é inicializada quando for utilizada | |
lazy var tutorialViewControllers: [UIViewController] = { | |
return [ | |
self.viewControllerChamada("Vermelho"), // Primeira página | |
self.viewControllerChamada("Azul"), // Segunda página | |
self.viewControllerChamada("Vermelho") // Terceira página | |
] | |
}() | |
// Agora nós temos tudo que precisamos para paginar: | |
// - Temos o page control para mostrar pro usuário em que página ele está | |
// - Temos o array com as páginas | |
// Precisamos configurar nossa Page View Controller para utilizar nossas | |
// view controllers na paginação | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// 1. Vamos definir que o `dataSource` e o `delegate` da nossa Page View Controller | |
// serão implementados em nossa classe. | |
self.delegate = self | |
self.dataSource = self | |
// Vai aparecer um erro por enquanto, mas já já ele some | |
// Agora vamos definir a página inicial da nossa Page View Controller | |
// 2. Pegamos a view controller na primeira posição do nosso array | |
if let primeiraViewController = self.tutorialViewControllers.first { | |
// 3. Definimos ela como a view controller inicial da nossa Page View Controller | |
self.setViewControllers([primeiraViewController], | |
direction: .forward, | |
animated: true, | |
completion: nil) | |
} | |
// 4. Por fim inicializamos nosso paginador | |
self.inicializarPaginador() | |
} | |
} | |
/*: | |
Perfeito! Até aqui só temos 2 errinhos nas linhas de delegate e dataSource, mas vamos resolver agora! | |
Como nós falamos para nossa Page View Controller que seus métodos de delegate e data source estarão implementados na nossa classe precisamos implementar os protocolos e os métodos necessários para que ela funcione. | |
Iremos fazer isso em uma extensão da classe para que nosso código fique mais limpo e organizado. | |
*/ | |
// 1. Criamos nossa extension e declaramos que vamos implementar os protocolos | |
// - UIPageViewControllerDataSource | |
// - UIPageViewControllerDelegate | |
extension TutorialViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate { | |
// 2. O primeiro método que iremos implementar é o método que define qual a View Controller que vem antes da View Controller atual na nossa paginação | |
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { | |
// Primeiro precisamos pegar o indice da view controller no nosso array | |
// Precisamos do indice para saber quem vem ANTES da view controller atual | |
guard let indiceDaViewController = self.tutorialViewControllers.index(of: viewController) else { | |
return nil | |
} | |
// Com isso podemos definir qual é o índice anterior ao atual | |
let indiceAnterior = indiceDaViewController - 1 | |
// Se o indice anterior for NEGATIVO então retornamos `nil` | |
if indiceAnterior < 0 { | |
return nil | |
} | |
// Se o indice anterior for MAIOR QUE a quantidade de elemento no nosso array, também retornamos `nil` | |
if indiceAnterior > self.tutorialViewControllers.count { | |
return nil | |
} | |
// Após testar a validade do indice, retornamos a View Controller do nosso array correspondente a essa posição | |
return self.tutorialViewControllers[indiceAnterior] | |
} | |
// 3. O segundo método que iremos implementar é o que define qual View Controller vem depois da View Controller atual na nossa paginação | |
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { | |
// Primeiro precisamos pegar o indice da view controller no nosso array | |
// Precisamos do indice para saber quem vem DEPOIS da view controller atual | |
guard let indiceDaViewController = self.tutorialViewControllers.index(of: viewController) else { | |
return nil | |
} | |
// Com isso podemos definir qual é o índice após ao atual | |
let proximoIndice = indiceDaViewController + 1 | |
// Precisamos saber quantas páginas tem no total na nossa Page View Controller | |
// Para isso pegamos a quantidade de elementos no nosso array de View Controllers | |
let quantidadeDeViewControllers = self.tutorialViewControllers.count | |
// Se o proximo indice for IGUAL a quantidade de controllers no array retornamos `nil` | |
if proximoIndice == quantidadeDeViewControllers { | |
return nil | |
} | |
// Se o próximo índice for MAIOR QUE a quantidade de de controllers no array retornamos `nil` | |
if proximoIndice > quantidadeDeViewControllers { | |
return nil | |
} | |
// Após testar a validade do indice, retornamos a View Controller do nosso array correspondente à proxima view controller na paginação | |
return self.tutorialViewControllers[proximoIndice] | |
} | |
// 4. Por fim vamos implementar o método para atualizarmos o nosso paginador quando o usuário passar a página no Page View Controller | |
// Ess método é chamado após a animação de transição entre as páginas | |
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { | |
// A primeira coisa que precisamos saber é qual a view controller atual no nosso Page View. Com isso será possivel saber se o usuário passou ou não a página após a animação ser concluída | |
// A propriedade `self.viewControllers` representa as View Controllers da sua Page View Controller. Como herdamos de UIPageViewController já temos acesso a essa propriedade. | |
// O primeiro elemento deste array representa a view controller atual na paginação | |
if let viewControllerAtual = self.viewControllers?.first { | |
// Com a view controller atual em mãos podemos saber em qual posição do nosso array de view controllers ela se encontra | |
if let indice = self.tutorialViewControllers.index(of: viewControllerAtual) { | |
// A página no nosso paginador é correspondente ao indice da View Controller atual no nosso array de View Controllers | |
self.paginador.currentPage = indice | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment