Navegação entre Telas no SwiftUI | NavigationStack 🇧🇷
-
Salve família, Michel aqui na área e nesse vídeo nós vamos explorar os principais conceitos ali de uma navegação básica em iOS.
O principal componente do SwiftUI para criar uma navegação básica é a Navigation Stack. A Navigation Stack tem um poder de exibir telas, criando uma espécie de navegação.
Então ela vai exibir para o seu usuário, a view selecionada dentro da sua interface. Não existe apenas a navegação stack, mas o que existe em comum entre todas elas é essa parte superior. Uma área destinada a trazer contexto para o conteúdo que está sendo exibido, onde é possível exibir um título e também ações para o seu usuário. Basicamente todas as pessoas que utilizaram em iPhone já utilizaram esse componente de navegação, e você pode ver nitidamente essa barra superior em qualquer uma dessas aplicações. Mas como é possível fazer com que uma navigation altere a tela que está sendo exibida? Nós podemos fazer isso através da navegação programática ou através da criação de o link.
Da mesma forma que existe em um site na internet criar um link e deixar com que os nossos usuários decidam para onde eles querem ir. A palavra stack significa pilha, e não aquela pilha de energia, mas aquela pilha de enpilhamento. Por exemplo, uma pilha de livros. Então, para que você consiga entender o funcionamento desse componente por trás dos panos, basta pensar dessa forma. Nós estamos empilhando essas views. Todas as vezes que os seus usuários clicaram em um link, nós iremos inserir uma nova tela dentro da navegação. É como se você tivesse olhando para essa caixa de cima para baixo, você não consegue ver as outras views.
Simplesmente a última view que foi inserida nessa caixinha. Todas as vezes que o seu usuário decidiu voltar nessa navegação, nós estamos removendo a tela mais recente. Até que finalmente todas as telas têm sido removidas, e o usuário consiga chegar à tela inicial da sua aplicação. Então vamos lá, família. Cria aí um projeto chamado Foot, vai ser o nosso FootApp, e a primeira tela desse app, como todos os apps que a gente cria em SwiftUI, é a ContentView. Qual é o nosso objetivo aqui? Nós queremos que, quando o usuário tocar em algum componente aqui na nossa primeira tela, nós vamos fazer com que ele navegue para uma segunda tela. Nós vamos chamar essa segunda tela de Detail View, uma tela de detalhe. Nós temos aqui uma segunda tela, que é a nossa tela, que é a nossa tela. Vou fazer o mesmo processo, eu vou copiar essa lei, porque a gente já cria aqui na ContentView, e vou levar ela lá para dentro da Detail View.
Então a gente já cria aqui na ContentView, e vou levar ela lá para тоже dentro da Detail View. Então, o show de bola, nós temos a nossa ContentView, aqui, que é a nossa home, nós temos a nossa ContentView, aqui, que é a nossa home, e nós temos a nossa Detail View, que é a nossa segunda tela. O primeiro passo para a gente criar uma navegação básica, é inserir a Navigation Stack.
Nós inserimos o nosso conteúdo da primeira tela, dentro de uma Navigation Stack.
Nós inserimos o nosso conteúdo da primeira tela dentro de uma Navigation Stack. Inserir um Vistaq, e agora vou inserir um link aqui na nossa interface, para que ele faça o disparo da primeira tela para a segunda tela. O nome é bem sugestivo, ele se chama Navigation Link. Eu vou pegar essa segunda opção aqui, de Title e Destination. O título do nosso link vai ser Link. E o destino do nosso link vai ser quem? Se você reparar, o destino é uma View. O nosso Xcode está nos cobrando uma View, e pode ser praticamente qualquer View. Nós já temos essa View criada, que é a nossa segunda tela, a Detail View. Nós temos, agora, um link logo abaixo da nossa Label de Home. Eu vou executar o nosso preview e clicar.Bom, ele inseriu na Navigation Stack uma nova visualização de destino, que, no caso, é a nossa segunda tela. Por isso, aconteceu essa transição da tela A até a tela D. E é importante notar aqui, turma, que lá em cima, nós já temos aquele botonzinho de Back de Voltar, que é praticamente aquele processo de remover a Detail View da nossa Stack. Então, quando eu clico nesse link, eu estou navegando para a segunda tela, inserindo a Detail View dentro da pilha. E, quando eu clico em Voltar, eu estou removendo a Detail View, fazendo com que a nossa Home View seja novamente exibida. O processo é bem simples, né, turma? Praticamente, é isso que você precisa fazer, para criar uma navegação básica aqui no seu projeto de SwiftUI.
Acho que o primeiro detalhe legal para mostrar para vocês é sobre o link. Nós temos aqui o título do nosso link, ou seja, o texto e o destino. Mas existem variações aqui do Navigation Link que podem facilitar na hora que vocês estiverem construindo a interface de vocês. Eu vou apagar, Deio Esque, e tem essa opção aqui, ó, que ele já começa com o destino, e ao invés de ser uma Taitoque, ele me cobra uma label. Então, agora, primeiro eu passo o destino, que a nossa Detail View, e a label não é mais um texto. Essa label agora me pede o quê? Um avil. Então, olha só, o resultado é literalmente o mesmo. Mas a novidade agora é que, ao invés de ficar trabalhando e customizando um navegação link, eu vou customizar o componente de texto. Posso colocar aqui alguma imagem, um outro componente mais interessante, para servir como o link, para a minha segunda tela dessa aplicação. Então, essa é uma forma diferente de você criar um link. Primeiro você passa o destino, e tudo que estiver entre as chaves do link vai ser o disparo para a segunda tela. O Navigation Link, ele também é inteligente e suficiente para se adequar, se acordo com o contexto que ele habita. Por exemplo, aqui no nosso código, nós estamos inserindo um navegação link dentro de um V-Stack, por isso ele tem esse comportamento dessa forma.
E se a gente tivesse alterando esse V-Stack para uma lista, vou tirar aqui a nossa label e vou alterar de V-Stack para lista. Dá uma olhada aqui no nosso preview.
Nós inserimos o nosso conteúdo da primeira tela, dentro de uma Navigation Stack. Inserir um Vistaq, e agora vou inserir um link aqui na nossa interface, para que ele faça o disparo da primeira tela para a segunda tela. O nome é bem sugestivo, ele se chama Navigation Link. Eu vou pegar essa segunda opção aqui, de Title e Destination.
O título do nosso link vai ser Link. E o destino do nosso link vai ser quem? Se você reparar, o destino é uma View. O nosso Xcode está nos cobrando uma View, e pode ser praticamente qualquer View. Nós já temos essa View criada, que é a nossa segunda tela, a Detail View. Nós temos, agora, um link logo abaixo da nossa Label de Home. Eu vou executar o nosso preview e clicar. Bom, ele inseriu na Navigation Stack uma nova visualização de destino, que, no caso, é a nossa segunda tela. Por isso, aconteceu essa transição da tela A até a tela D.
E é importante notar aqui, turma, que lá em cima, nós já temos aquele botonzinho de Back de Voltar, que é praticamente aquele processo de remover a Detail View da nossa Stack. Então, quando eu clico nesse link, eu estou navegando para a segunda tela, inserindo a Detail View dentro da pilha. E, quando Dá uma olhada aqui no nosso preview. Ele já entendeu que agora ele habita dentro de uma lista, e já existe esse símbolo que seria o nosso Disclosure. Por exemplo, se eu chegar aqui em cima dele, e criar-se só um texto. Agora, a primeira linha não contém mais aquele símbolo. Esse Disclosure Indicator aqui, ou chevron, depende da forma como você costuma chamar esse cara, mas isso aqui é uma boa prática de usabilidade. Você informar para o usuário que existe uma ação ao tocar naquela célula da lista.
Também existem algumas áreas exclusivas aqui, proporcionadas pela Navigation Stack, que vão ajudar o nosso usuário a compreender a informação e interagir com a informação que está sendo exibida ali na nossa interface. Essa área exclusiva é conhecida como Navigation Bar, ou também como TOO Bar. São aquelas barras superiores onde nós podemos inserir títulos e até botões de interação. Por mais que essa barra não esteja aparecendo aqui na nossa aplicação, ela já existe. Quando nós clicamos em detail, aquele botão de Back está sendo exibido ali em cima. Então como que a gente criou um título para trazer mais contexto aqui para essa tela de Home View? Nós fazemos isso através dos modificadores. Navigation Title.
Então agora nós já temos aquele título ali em cima e quando clicamos na segunda tela, reparem no botão lá em cima. Agora ele não se chama mais Back e sim o título que a gente inseriu na primeira tela. Uma outra customização interessante que você pode fazer aqui é forçar com que esse título não esteja nesse formato grande aqui, que ele esteja sempre minimizado ali ao centro da sua barra superior. Navigation Bar, Title, Display. Nós temos aqui algumas opções. Inline, o nosso título fica pequenininho na nossa barra superior.
Ou podemos utilizar o Large, que é basicamente aquele que nós estávamos utilizando. Esse comportamento aqui de deixar uma exibição de título larga e quando puxarmos ali, está o fizemos no scroll do componente, ele mostra ali o título pequenininho lá em cima, é o comportamento automático, que é essa opção aqui, point automatic. Mas você não precisa literalmente inserir essa opção, porque ela já é a opção pré-definida aqui pelo SwiftUI. Também existem customizações de toolbar, que conseguimos literalmente inserir botões nessas barras superiores. Antes de avançarmos, eu só queria mostrar para vocês um erro muito comum, que muita gente que está começando acaba cometendo e se embolando aqui na hora de criar as barras superiores.
Esse título pertence ao conteúdo e não à Navigation Stack. Imaginem como se isso fosse um porta-retrato. A Navigation Stack é o nosso porta-retrato e a lista, no caso, é o conteúdo que está sendo exibido nesse porta-retrato, ou seja, a foto que está sendo exibida ali. Então, tomem bastante cuidado na hora de inserir os títulos. Muita gente acaba inserindo esses títulos na Navigation Stack aqui embaixo, e olha só o que acontece. Vocês não vão conseguir ter esse resultado. Então, lembrem-se, essas informações de título pertencem ao conteúdo. Esse título serve para trazer mais contexto sobre aquele conteúdo. Eu vou abrir aqui a nossa Diteio.
Eu quero que vocês percebam uma coisa. Reparem que, em nenhum momento, nós estamos inserindo aqui uma Navigation Stack. O nosso projeto, o SwiftUI mesmo, identifica que lá na primeira tela existia uma Navigation Stack, que solicitou a Diteio View. A partir do momento que a Diteio View é inserida lá naquela Navigation Stack, ela ganha aquelas informações de barra superior. Mas, isso é a gente que executa aqui na nossa Diteio View, fazer customizações, por exemplo, de título, que é o que fizemos lá na outra tela. Pensei esse título e nada aconteceu aqui no nosso preview. Então, como que eu faço isso? Eu tenho que inserir agora uma outra Navigation Stack. Não, isso não é uma boa ideia de se fazer. A Navigation Stack já existe. A única coisa que vocês precisam fazer agora é exibir essa informação feita aqui no seu preview da direita, para que vocês possam ver isso em ação. O código aqui embaixo é o código responsável pela exibição do nosso preview aqui na direita. Então, se vocês repararem, nós estamos literalmente pedindo para que ele exiba uma Diteio View.
Como não podemos inserir uma nova Navigation Stack lá dentro da Diteio View, podemos simular o uso de uma Navigation Stack aqui fora. Agora, sim, o nosso título apareceu lá em cima. Neste caso, temos apenas um texto sendo transformado em um link, que faz o disparo da tela A para a tela B. Mas, é muito comum algumas pessoas inserirem botões de interação dentro desses links.
Então, da mesma forma que eu coloquei um texto para seu link, eu também posso colocar um botão. Parece que tudo está funcionando, mas qual é o problema então? O problema é que existe um conflito de atenção do toque. O NavigationLink foi criado para captar os toques do usuário, e o botão também foi criado para captar toques do usuário. Se a gente tivesse inserindo aqui um print, por exemplo, para tentar exibir lá no console. Toda vez que o usuário tocar nesse botão, a gente vai conseguir ver esse conflito de interesses ali de atenção acontecendo.
Eu vou executar o nosso projeto, porque esse tipo de coisa não dá para ver ali no nosso preview, e vou abrir a nossa barra de console também. Esse primeiro toque, eu vou fazer simplesmente na linha 'Toquei', nada foi exibido ali no nosso console. O segundo toque, eu vou dar literalmente em cima do nosso botão. 'Toquei', de novo, nada foi exibido no nosso console, ou seja, está tendo ali um conflito de interesses, por mais que esteja botando esse 'pressed' aqui dentro da ação do botão, ele não está conseguindo fazer o disparo. Como é que a gente consegue contornar esse tipo de situação? A gente consegue contornar isso inserindo o modificador 'BorderlessButtonStyle'. Essa aqui não é a única forma. Existem outras formas de evitar com que isso aconteça, mas isso aqui é uma forma que vai te ajudar nessas situações. Eu vou executar novamente. Quando eu tocar no botão, tudo está funcionando lá no console. E agora, quando eu tocar na nossa célula, também estamos fazendo a transição da tela A para a tela A. Então, essa aqui é uma alternativa que você pode usar para resolver situações como essa. Não que seja proibido inserir botões dentro de NavigationLink. Não é proibido, você pode fazer isso mais tome cuidado, porque isso é uma coisa que pode te trazer problemas lá na frente. Na maioria dos casos, você consegue resolver essas situações simplesmente com uso de NavigationLink. Eu vou voltar a utilizar aqui um VStack, só para vocês verem a diferença do NavigationLink para o Button. Coloquei um abaixo do outro. Se vocês observarem, vocês vão perceber que, visualmente, eles são praticamente a mesma coisa. Então, tome cuidado quando vocês estiverem utilizando os botões dentro de NavigationLink. Faça uma reflexão para ver se é realmente preciso fazer dessa forma. Uma das coisas que muita gente se pergunta é como é possível passar valores da tela A para a tela B, como a gente consegue enviar um valor para que essa informação seja utilizada lá na segunda tela. E porque as pessoas perguntam isso? Porque é muito comum você criar na primeira tela uma lista de informações e na segunda tela um detalhamento da informação selecionada. Então, vamos lá. O nosso desafio agora vai ser passar um valor da tela A de Home para a nossa DT. Eu vi um. Então, o primeiro passo aqui é criar uma variável que vai guardar o valor do título.
Ao invés de inserir 'DT' ou aqui nesse título, nós vamos inserir um valor que foi passado lá da primeira tela. Quando a gente criou essa variável, o Swift já sabe que ela é uma string por conta do nosso Type inference. Então, ele já sabe que aqui existe os dois pontos e essa string. E nós estamos inserindo um valor lá dentro dessa variável. Mas para cobrar essa informação sem que ela seja pré-definida, a gente não faz essa atribuição. Então, agora, na linha 11, nós estamos dizendo que existe uma variável de título, mas não existe valor aí dentro. O nosso Swift, o nosso SwiftUI vai ficar doidinho, querendo saber. Cara, o que eu vou colocar aqui dentro? Eu não posso resolver sozinho essa informação. Então, a partir de agora, ele vai cobrar de todo mundo que tentar exibir a DT.O.V.O um valor de título. Se você olhar aqui embaixo, você vai perceber que na nossa pré-visualização já existe um erro, porque ele está tentando exibir uma DT.O.V.O e ele não sabe qual título ele insere ali dentro.
A gente pode clicar aqui no fix, vai aparecer esse título, e a gente pode colocar aqui. Mas por que a gente ainda está tendo erro aqui em cima? Porque a nossa DT.O.V.O também está sendo solicitada lá na primeira tela. Vamos voltar lá. O nosso Xcode já detectou que existe um erro aqui, e ele está cobrando a partir de agora, que sempre que você faça a exibição da DT.O.V.O, você passe um título, senão, vai existir um erro. Nós temos o NavigationLink. O destino desse NavigationLink vai ser para a DT.O.V.O, e o título da DT.O.V.O vai ser 'fenômeno'. Esse processo é conhecido como Injeção de Dependência. Nós vamos injetar na DT.O.V.O a informação de título. Então, esse tipo de interface é uma das interfaces mais utilizadas aqui no iOS, quando nós temos na primeira tela uma lista com vários componentes, e na segunda tela um detalhamento da informação selecionada. Eu vou incrementar aqui o nosso exemplo para que vocês possam entender que isso é em uma situação mais real aqui de código. Eu vou criar uma nova variável que vai ser o nosso time de jogadores, e essa variável vai ser um array de Strings, com os nomes dos jogadores que eu selecionei. Ao invés de criar dentro da lista um link manualmente, eu vou criar uma sequência de links customizados. Para cada jogador, eu vou exibir um novo link. Então, é isso. Dentro da lista, nós estamos percorrendo todo o array de jogadores que a gente criou lá em cima, e para cada um desses jogadores, nós criamos um link.
O conteúdo desse link vai ser o nome do jogador, e o destino desse link vai ser a DT.O.V.O, passando o nome do jogador. E se você reparar, o disclosure já existe em cada uma dessas links da lista. Quando eu clicar em KK, o nosso título, lá da outra tela, já foi preenchido porque nós fizemos uma injeção de dependência. Nós injetamos esse valor na segunda tela. Eu também queria passar uma dica interessante para vocês que pode ajudar bastante quando vocês estiverem criando as navegações de vocês através de Navigation Stack. Quando você cria um projeto em SwiftUI, automaticamente o Xcode cria para você esse arquivo App.
É o arquivo que define a primeira tela da sua aplicação. Se você olhar aqui embaixo, a primeira tela da sua aplicação é a ContentView. Mas, dependendo da situação, você pode colocar aqui, logo na raiz, uma NavigationView. Então, a partir de agora, toda vez que o nosso app for inicializado, primeiro ele vai criar uma NavigationView, e depois exibir a nossa ContentView. Como eu já falei para vocês, nós não podemos colocar NavigationView dentro de NavigationView. Nesses casos, a gente precisa fazer o quê? Remover ela daqui de dentro da ContentView, porque essa tela já vai ser exibida automaticamente dentro de uma stack. Dessa forma, a sua ContentView vai ter apenas conteúdo.
Mas o nosso preview aqui na direita parou de funcionar. Isso porque, no código aqui embaixo de pré-visualização dessa tela, nós estamos exibindo apenas a ContentView. E agora, a NavigationView não faz parte da ContentView. Ela está sendo criada por fora. Então, da mesma forma que a gente fez na DT.O.V.O, nós vamos simular uma NavigationView aqui dentro. A navegação do SwiftUI foi, por muito tempo, o calcanhar de Aquiles.
E aí, a pô, vem ano após ano, incrementando essa parte. Nós tivemos várias melhorias e uma NavigationView foi uma dessas melhorias. Você pode se deparar e, durante a sua jornada de aprendizado, com um componente muito parecido com esse, que se chama NavigationView. A NavigationView foi, por muitos anos, o carro chefe de navegação do SwiftUI. Eles são muito parecidos. A diferença é que o NavigationStack consegue abordar as coisas de uma forma diferente. Existem exclusividades da NavigationStack que podem fortalecer muito o seu código, principalmente quando a gente tiver incrementando o conceito de Data-Driven, navegação baseada em dados.
Como, por exemplo, o NavigationDestinationLink, o Puff, mais relaxa, que é um papo mais para frente. Nesse vídeo, nós exploramos os principais conceitos de navegação básica através da NavigationStack. Vocês viram também a customização das barras superiores, como criar links e customizar esses links. E nesse vídeo vocês também viram alguns macetes, como a utilização de botões e a injeção de dependência na hora de transmitir valores de uma tela para a outra. Eu espero que vocês tenham gostado, vamos para cima e a gente se encontra no próximo vídeo.