1. Antes de começar
Existem dispositivos Android de várias formas, tamanhos e formatos. Projete o app para rodar nesses diferentes tipos de dispositivos, desde os de tela pequena até os de tela maior. Os desenvolvedores que criam apps prontos para produção podem oferecer suporte ao Android Wear, ao Android Auto e ao Android TV, mas esses tópicos estão fora do escopo deste curso. Quando seu app oferece suporte a uma maior variedade de telas, ele pode ser usado por mais usuários com dispositivos diferentes.
O app precisa ter um layout flexível. Em vez de definir o layout com dimensões rígidas para uma determinada proporção e tamanho da tela, o layout precisa ser adaptável a vários tamanhos e orientações. O mesmo princípio se aplica quando o app é executado em um dispositivo dobrável, no qual o tamanho e a proporção da tela podem mudar. Ao final deste codelab, você vai ver uma breve introdução aos dispositivos dobráveis.
Pré-requisitos
- Como fazer o download e executar o código no Android Studio.
- Estar familiarizado com os componentes da arquitetura do Android,
ViewModel
eLiveData
. - Noções básicas sobre os componentes de navegação.
O que você vai aprender
- Como adicionar o
SlidingPaneLayout
ao app.
O que você vai criar
- Atualizar o app "Sports" para se adaptar a telas grandes.
Pré-requisitos
- Um computador com o Android Studio instalado.
- O código inicial do app Sports.
Fazer o download do código inicial para este codelab
Este codelab oferece um código inicial para você estender com os recursos ensinados. O código inicial pode conter um código que você já conheceu em codelabs anteriores e também trechos novos que serão apresentados nos próximos codelabs.
Para fazer o download do código deste codelab no GitHub e abrir no Android Studio, siga as etapas abaixo.
- Inicie o Android Studio.
- Na janela Welcome to Android Studio, clique em Get from VCS.
- Na caixa de diálogo Get from Version Control, verifique se a opção Git está selecionada no menu Version control.
- Cole o URL do código fornecido na caixa URL.
- Você pode mudar o campo Directory para algo diferente do padrão sugerido, se preferir.
- Clique em Clone. O Android Studio começará a buscar o código.
- Aguarde o Android Studio abrir.
- Selecione o módulo correto para o código inicial, o app ou a solução do codelab.
- Clique no botão Run
para criar e executar o código.
2. Assistir ao vídeo de orientações (opcional)
Se você quiser acompanhar a conclusão deste codelab por um dos instrutores do curso, assista ao vídeo abaixo.
Recomendamos abrir o vídeo em tela cheia usando o ícone no canto inferior direito da reprodução para ter uma visualização melhor do Android Studio e do código.
Esta etapa é opcional. Você pode pular o vídeo e começar a seguir as instruções do codelab.
3. Visão geral do app inicial
O app Sports consiste em duas telas. A primeira tela exibe a lista de esportes. O usuário pode selecionar um item de um esporte específico, em seguida, a segunda tela vai ser exibida. A segunda tela é uma tela de detalhes que exibe as notícias relacionadas ao esporte selecionado. A tela de detalhes exibe o texto marcador de posição para simplificar a implementação.
Tutorial em etapas do código inicial
O código inicial que foi transferido por download tem os layouts da tela de lista e da tela de detalhes pré-criados para você. Nesse programa de aprendizagem, você vai se concentrar apenas em adaptar o app a telas grandes. Você vai usar o SlidingPaneLayou
t para aproveitar a tela grande. Confira abaixo um breve tutorial sobre alguns dos arquivos para começar.
fragment_sports_list.xml
- Abra
res/layout/fragment_sports_list.xml
na visualização Design. - Esse arquivo contém o layout da primeira tela do app, que é a lista de esportes.
- Esse layout consiste em uma Recyclerview que mostra uma lista de notícias esportivas.
sports_list_item.xml
- Abra
res/layout/sports_list_item.xml
na visualização Design. - Ele contém o layout de cada item na Recyclerview.
- Esse layout tem uma imagem de miniatura do esporte, o título "News" (Notícias) e um texto marcador de posição para uma breve notícia sobre esportes.
fragment_sports_news.xml
- Abra
res/layout/fragment_sports_news.xml
na visualização Design. - Esse arquivo contém o layout da segunda tela do app. A tela é exibida quando o usuário seleciona um esporte na Recyclerview.
- Esse layout inclui um banner da imagem do esporte e um texto marcador de posição para as notícias relacionadas.
main_activity.xml e content_main.xml
Esses dois elementos definem o layout da atividade principal com um único fragmento.
navigation/nav_graph.xml
O gráfico de navegação contém dois destinos, um para listas de esportes e outro para notícias esportivas.
Pasta res/values
Você já conhece os arquivos de recurso nesta pasta.
- O arquivo
colors.xml
contém as cores de tema usadas no app. - O arquivo
strings.xml
contém todas as strings que o app precisa. - O arquivo
themes.xml
contém a personalização da IU para o app.
MainActivity.kt
Esse é o arquivo do código padrão gerado pelo modelo para definir a visualização do conteúdo da atividade como main_activity.xml
. O método onSupportNavigateUp()
foi substituído para processar a navegação padrão "Para cima" na barra de apps.
model/Sport.kt
Essa é uma classe de dados que define os dados a serem exibidos em cada linha da lista de esportes da Recyclerview.
data/SportsData.kt
Esse arquivo contém uma função chamada getSportsData()
, que retorna uma ArrayList
pré-preenchida com dados de esporte fixados no código.
SportsViewModel.kt
Este é o ViewModel
compartilhado do app. O ViewModel
é compartilhado pelo SportsListFragment
, que é a primeira tela com a lista de esportes e o NewsDetailsFragment
, que é a segunda com notícias detalhadas sobre esportes.
- A propriedade
_currentSport
é do tipoMutableLiveData,
que armazena o esporte atual selecionado pelo usuário. A propriedadecurrentSport
é a propriedade de apoio para_currentSport
e é exposta como a versão pública somente leitura de outras classes. - A propriedade
_sportsData
contém a lista de dados sobre esportes. Semelhante à propriedade anterior,sportsData
é a versão pública somente leitura dessa propriedade. - O bloco
init{}
do inicializador inicializa_currentSport
e_sportsData
. O_sportsData
é inicializado com toda a lista de esportes dodata/SportsData.kt
. O_currentSport
é inicializado com o primeiro item da lista. - A função
updateCurrentSport()
usa uma instância deSports
e atualiza_currentSport
com o valor transmitido.
SportsAdapter.kt
Esse é o adaptador para a RecyclerView
. No construtor, o listener de clique é transmitido. A maior parte do código neste arquivo é código boilerplate que você já conheceu em codelabs anteriores.
SportsListFragment.kt
Esse é o primeiro fragmento de tela, em que a lista de esportes é exibida.
- A função
onCreateView()
infla o XML do layoutfragment_sports_list
usando o objeto de vinculação. - A função
onViewCreated()
configura o adaptadorRecyclerView
. Ela atualiza o esporte selecionado pelo usuário como o esporte atual noViewModel
compartilhado, oSportsViewModel
. Ela navega até a tela de detalhes com notícias esportivas e envia a lista de esportes para o adaptador que será mostrado usandosubmitList(List)
.
NewsDetailsFragment.kt
Essa é a segunda tela do app, onde é exibido o texto marcador de posição para as notícias esportivas.
- A função
onCreateView()
infla o XML do layoutfragment_sports_news
usando o objeto de vinculação. - A função
onViewCreated()
anexa um observador na propriedadecurrentSport
doSportsViewModel
para atualizar a interface automaticamente quando os dados mudam. No observador, o título, a imagem e as notícias dos esportes são atualizados.
Compilar e executar o aplicativo
- Crie e execute o app em um emulador ou dispositivo. Selecione qualquer item na lista de esportes e o app navegará para a segunda tela com o texto marcador de posição das notícias.
4. Padrão de detalhes de lista
O app inicial atual não aproveita ao máximo o espaço da tela em dispositivos maiores, como tablets. Para resolver esse problema, você vai exibir a IU do app usando o padrão de detalhes de lista, que vai aprender neste codelab.
Executar o app em um tablet
Nesta tarefa, você vai criar um emulador com um perfil para tablet. Depois de criar o emulador, você vai executar o código inicial do app de esportes e observará a IU.
- No Android Studio, acesse Tools > AVD Manager.
- A janela Android Virtual Device Manager vai ser exibida. Clique em + Create New Virtual Device... que é mostrado na parte de baixo.
- A janela Virtual Device Configuration é exibida. Aqui, você vai configurar o hardware e o SO do emulador. Clique em Tablet no painel à esquerda. Selecione Pixel C ou qualquer outro perfil de hardware semelhante no painel do meio.
- Clique em Next.
- Selecione a imagem mais recente do sistema; no momento da criação deste codelab é R (nível 30 da API).
- Clique em Next.
- É possível renomear o dispositivo virtual agora. Isso é opcional.
- Clique em Finish.
- Você vai voltar à janela Android Virtual Device Manager. Clique no ícone de inicialização
ao lado do dispositivo virtual recém-criado.
- O emulador com perfil para tablet será iniciado. Isso pode levar algum tempo.
- Feche a janela do Android Virtual Device Manager.
- Execute o app de esportes no emulador recém-criado.
Observe que em dispositivos grandes, o app não usa a tela inteira. Os detalhes e listas são mais eficientes em uma tela grande do que uma lista. Um padrão de detalhes do item, também conhecido como padrão mestre, mostra uma lista de itens em um lado do layout e os detalhes ao lado dele quando você toca em um item. Normalmente, essas visualizações são exibidas somente em telas grandes, como tablets, porque elas têm mais espaço para exibir mais conteúdo.
As imagens abaixo são um exemplo de padrão de detalhe e listas:
Os padrões de detalhes e listas acima mostram uma lista de itens à esquerda e detalhes do item selecionado à direita.
Da mesma forma, se você usar o padrão acima no app de esportes, o fragmento de notícias vai ser a tela de detalhes.
Neste codelab, você vai aprender a implementar a interface de detalhes e listas usando SlidingPaneLayout
.
5. Padrão SlidingPaneLayout
Uma interface de detalhes e listas pode precisar se comportar de maneira diferente dependendo do tamanho da tela. Em telas grandes, há espaço suficiente para exibir a lista e os painéis de detalhes lado a lado. Clicar em um item da lista mostra os detalhes no painel de detalhes. No entanto, em telas pequenas, elas aparecem agrupadas. Em vez de apresentar os dois painéis de uma vez, é melhor os mostrar um de cada vez. Inicialmente, o painel de lista preenche a tela. Tocar em um item substitui o painel da lista pelo painel de detalhes desse item, que também preenche a tela.
Você vai aprender a usar um SlidingPaneLayout para gerenciar a lógica a fim de selecionar a experiência do usuário apropriada com base no tamanho da tela atual.
Observe como o painel de detalhes desliza sobre o painel de lista em telas menores.
Confira abaixo imagens que ilustram como o SlidingPaneLayout
é mostrado em uma tela menor. Observe como o painel de detalhes se sobrepõe ao painel da lista quando um item da lista é selecionado. Portanto, os dois painéis estão sempre presentes.
Dessa forma, o SlidingPaneLayout
oferece suporte à exibição de dois painéis lado a lado em dispositivos maiores, enquanto se adapta automaticamente para mostrar apenas um painel por vez em dispositivos menores, como smartphones.
6. Adicionar dependências de biblioteca
- Abra o
build.gradle (Module: Sports.app)
- Na seção de
dependencies
, inclua a dependência abaixo para usar oSlidingPaneLayout
no app:
dependencies {
...
implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0-beta01"
}
7. Configurar o XML de fragmento da lista de esportes
Nesta tarefa, você converte o layout raiz de fragment_sports_list
para SlidingPaneLayout
. Como você já sabe, o SlidingPaneLayout
oferece um layout de dois painéis horizontais para uso no nível mais alto de uma IU. Esse layout usa o primeiro painel como uma lista de conteúdo ou um navegador, subordinado a uma visualização de detalhes principal para exibir conteúdo no outro painel.
No app Sports, o primeiro painel é a RecyclerView
exibindo a lista de esportes e o segundo painel exibe as notícias sobre esportes.
Adicionar o SlidingPaneLayout
- Abra o
fragment_sports_list.xml
Observe que o layout raiz é umFrameLayout
. - Mude
FrameLayout
paraandroidx.slidingpanelayout.widget.SlidingPaneLayout.
.
<androidx.slidingpanelayout.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SportsListFragment">
<androidx.recyclerview.widget.RecyclerView...>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
- Adicione um atributo
android:id
aoSlidingPaneLayout
e atribua a ele o valor@+id/sliding_pane_layout
.
<androidx.slidingpanelayout.widget.SlidingPaneLayout
...
android:id="@+id/sliding_pane_layout"
...>
Adicionar um segundo painel ao SlidingPaneLayout
Nesta tarefa, você vai adicionar um segundo filho ao SlidingPaneLayout
. Ele é exibido como o painel de conteúdo à direita.
- Em
fragment_sports_list.xml
, abaixo daRecyclerView
, adicione um segundo filho,androidx.fragment.app.FragmentContainerView
. - Adicione os atributos obrigatórios,
layout_height
elayout_width
, àFragmentContainerView
. Dê a eles o valor dematch_parent
. Esses valores serão atualizados mais tarde.
<androidx.fragment.app.FragmentContainerView
android:layout_height="match_parent"
android:layout_width="match_parent"/>
- Adicione um atributo
android:id
àFragmentContainerView
e atribua a ele o valor@+id/detail_container
.
android:id="@+id/detail_container"
- Adicione
NewsDetailsFragment
àFragmentContainerView
usando o atributoandroid:name
.
android:name="com.example.android.sports.NewsDetailsFragment"
Atualizar o atributo layout_width
O SlidingPaneLayout
usa a largura dos dois painéis para determinar se eles vão ser mostrados lado a lado. Por exemplo, se o painel da lista for medido para ter um tamanho mínimo de 300dp
e o painel de detalhes precisar de 400dp
, o SlidingPaneLayout
mostra automaticamente os dois painéis lado a lado, contanto que haja, pelo menos, 700dp
de largura disponível.
As visualizações filhas vão se sobrepor se a largura combinada exceder a disponível no SlidingPaneLayout
. Nesse caso, as visualizações filhas se expandem para preencher a largura disponível no SlidingPaneLayout
.
Para determinar a largura das visualizações filhas, é necessário ter algumas informações básicas sobre as larguras da tela do dispositivo. A tabela abaixo mostra a lista de pontos de interrupção opinativos para você desenvolver e testar em layouts redimensionáveis de aplicativos. Eles foram escolhidos para equilibrar a simplicidade do layout com a flexibilidade de otimizar o app para casos únicos.
Largura | Ponto de interrupção | Representação do dispositivo |
Largura compacta | < 600 dp | 99,96% dos smartphones no modo retrato |
Largura média | 600 dp+ | 93,73% dos tablets no modo portraitLarge com as telas internas desdobradas no modo retrato |
Largura expandida | 840 dp+ | 97,22% dos tablets no modo landscapeLarge com as telas internas desdobradas no modo paisagem |
No app Sports, você quer exibir um único painel, a lista de esportes em smartphones, destinados a dispositivos com largura inferior a 600dp
. Para exibir os dois painéis em tablets, a largura combinada precisa ser maior que 840dp
. Você pode usar uma largura de 550dp
para o primeiro elemento filho, a visualização de reciclagem, e 300dp
para o segundo filho, a FragmentContainerView
.
- Em
fragment_sports_list.xml
, mude a largura do layout daRecyclerView
para550dp
e a daFragmentContainerView
para300dp
.
<androidx.recyclerview.widget.RecyclerView
...
android:layout_width="550dp"
.../>
<androidx.fragment.app.FragmentContainerView
...
android:layout_width="300dp"
.../>
- Execute o app no emulador com o perfil de tablet e um emulador com o perfil do smartphone.
Observe que dois painéis são mostrados no tablet. Você vai corrigir a largura do segundo painel no tablet na próxima etapa.
- Execute o app no emulador com o perfil do smartphone.
Adicionar layout_weight
Nesta tarefa, você vai corrigir a IU no tablet e fazer o segundo painel ocupar todo o espaço restante.
O SlidingPaneLayout
permite definir como o espaço restante é dividido após a medição usando o parâmetro de layout layout_weight
em visualizações filhas se elas não se sobrepuserem. Esse parâmetro se aplica somente à largura.
- No arquivo
fragment_sports_list.xml
, adicionelayout_weight
àFragmentContainerView
e atribua o valor1
a ela. Agora, o segundo painel se expande para preencher o espaço restante depois que o painel da lista for medido.
android:layout_weight="1"
- Execute o app.
Parabéns! Você adicionou SlidingPaneLayout
com sucesso. Você ainda não terminou. Você precisa implementar a navegação de retorno e atualizar o segundo painel quando um item é selecionado na lista. Isso será implementado em uma tarefa futura.
8. Trocar o painel de detalhes
Execute o app no emulador com o perfil do tablet. Selecione uma opção na lista de esportes. O app navega até o painel de detalhes.
Nesta tarefa, você vai corrigir esse problema. No momento, o conteúdo do painel duplo está sendo atualizado com o esporte selecionado e, em seguida, o app navega para o NewsDetailsFragment
.
- No arquivo
SportsListFragment
, na funçãoonViewCreated()
, localize as linhas abaixo que acessam a tela de detalhes.
// Navigate to the details screen
val action = SportsListFragmentDirections.actionSportsListFragmentToNewsFragment()
this.findNavController().navigate(action)
- Substitua as linhas acima por este código:
binding.slidingPaneLayout.openPane()
Chame openPane()
no SlidingPaneLayout
para trocar o primeiro painel pelo segundo. Isso não será notado se os dois painéis estiverem visíveis, como em um tablet.
- Execute o app no emulador de tablet e smartphone. Observe que o conteúdo do painel duplo está sendo atualizado corretamente.
Na próxima tarefa, você vai adicionar ao app a navegação de retorno personalizada.
9. Adicionar navegação de retorno personalizada
Em dispositivos menores em que os painéis de lista e de detalhes se sobrepõem, garanta que o botão "Voltar" do sistema leve o usuário do painel de detalhes de volta ao painel de listas. Para fazer isso, ofereça uma navegação de retorno personalizada e conecte um OnBackPressedCallback
ao estado atual do SlidingPaneLayout
.
Navegação de retorno
A navegação de retorno é a forma como os usuários se movem para trás no histórico de telas que visitaram anteriormente. Todos os dispositivos Android oferecem um botão "Voltar" para esse tipo de navegação. Dependendo do dispositivo Android do usuário, esse botão pode ser um botão físico ou de software.
Navegação de retorno personalizada
O Android mantém uma backstack de destinos à medida que o usuário navega no app. Isso normalmente permite que o Android navegue corretamente para destinos anteriores quando o botão "Voltar" é pressionado. No entanto, há casos em que o app precisa implementar um comportamento de retorno próprio para oferecer a melhor experiência do usuário possível.
Por exemplo, ao usar uma WebView, como um navegador Chrome, talvez você queira modificar o comportamento padrão do botão "Voltar" para permitir que o usuário navegue pelo histórico de navegação na Web em vez das telas anteriores do app.
Da mesma forma, você precisa fornecer uma navegação de retorno personalizada para o SlidingPaneLayout
e navegar do app do painel de detalhes até o painel da lista.
Implementar a navegação de retorno personalizada
Para implementar a navegação de retorno personalizada no app Sports, você precisa:
- Definir um callback personalizado para substituir o
OnBackPressedCallback
quando o botão "Voltar" for pressionado. - Registrar e adicionar a instância de callback.
Primeiro, defina o callback personalizado.
- No arquivo
SportsListFragment
, adicione uma nova classe abaixo da definição da classeSportsListFragment
. Dê o nomeSportsListOnBackPressedCallback
a ela. - Transmita uma instância
private
doSlidingPaneLayout
como um parâmetro do construtor.
class SportsListOnBackPressedCallback(
private val slidingPaneLayout: SlidingPaneLayout
)
- Estenda a classe do
OnBackPressedCallback
. A classeOnBackPressedCallback
processa callbacksonBackPressed
. Você vai corrigir o erro do parâmetro do construtor em breve.
class SportsListOnBackPressedCallback(
private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback()
O construtor de OnBackPressedCallback
aceita um valor booleano para o estado inicial ativado. Somente quando um callback estiver ativado (isto é, isEnabled()
retornar verdadeiro), o agente vai chamar o método handleOnBackPressed()
do callback para processar o evento do botão "Voltar".
- Transmita
slidingPaneLayout.
isSlideable
*&& slidingPaneLayout.isOpen
* como parâmetro do construtor paraOnBackPressedCallback
. O booleanoisSlideable
só será verdadeiro se o segundo painel for deslizável, ou seja, mostrado em uma tela menor, e um único painel estiver sendo exibido. O valor deisOpen
serátrue
quando o segundo painel (o painel de conteúdo) estiver completamente aberto.
class SportsListOnBackPressedCallback(
private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen)
Esse código garante que o callback seja ativado somente nos dispositivos de tela menores e quando o painel de conteúdo estiver aberto.
- Para corrigir o erro sobre o método não implementado, clique na lâmpada vermelha
e selecione Implement members.
- Clique em "ok" no pop-up Implement members para substituir o método
handleOnBackPressed
.
A classe ficará assim:
class SportsListOnBackPressedCallback(
private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen) {
/**
* Callback for handling the [OnBackPressedDispatcher.onBackPressed] event.
*/
override fun handleOnBackPressed() {
TODO("Not yet implemented")
}
}
- Na função
handleOnBackPressed()
, exclua a instrução TODO e adicione o código abaixo para fechar o painel de conteúdo e voltar ao painel da lista.
slidingPaneLayout.closePane()
Monitorar os eventos do SlidingPaneLayout
Além de lidar com eventos de pressionar, você precisa detectar e monitorar eventos relacionados ao painel deslizante. À medida que o painel de conteúdo é deslizado, o callback precisa ser ativado ou desativado. Você vai usar o PanelSlideListener
para fazer isso.
A interface SlidingPaneLayout.PanelSlideListener
contém três métodos abstratos: onPanelSlide()
, onPanelOpened()
e onPanelClosed()
. Esses métodos são chamados quando o painel de detalhes desliza, é aberto, e fechado, respectivamente.
- Estenda a classe
SportsListOnBackPressedCallback
deSlidingPaneLayout.PanelSlideListener
. - Para resolver o erro, implemente os três métodos. Clique na lâmpada vermelha e selecione Implement members no Android Studio.
- A classe
SportsListOnBackPressedCallback
precisa ser semelhante a esta:
class SportsListOnBackPressedCallback(
private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen),
SlidingPaneLayout.PanelSlideListener{
override fun handleOnBackPressed() {
slidingPaneLayout.closePane()
}
override fun onPanelSlide(panel: View, slideOffset: Float) {
TODO("Not yet implemented")
}
override fun onPanelOpened(panel: View) {
TODO("Not yet implemented")
}
override fun onPanelClosed(panel: View) {
TODO("Not yet implemented")
}
}
- Remova as instruções TODO.
- Ative o callback
OnBackPressedCallback
quando o painel de detalhes estiver aberto (visível). Para isso, chame a funçãosetEnabled()
e transmitatrue
. Coloque o código abaixo no métodoonPanelOpened()
:
setEnabled(true)
- O código acima pode ser simplificado usando a sintaxe de acesso a propriedades.
override fun onPanelOpened(panel: View) {
isEnabled = true
}
- Da mesma forma, defina
isEnabled
comofalse
quando o painel de detalhes estiver fechado.
override fun onPanelClosed(panel: View) {
isEnabled = false
}
- A etapa final para concluir o callback é adicionar a classe de listener
SportsListOnBackPressedCallback
à lista de listeners que serão notificados nos eventos de deslize do painel de detalhes. Adicione um blocoinit
à classeSportsListOnBackPressedCallback
. No blocoinit
, faça uma chamada paraslidingPaneLayout.addPanelSlideListener()
transmitindothis
.
init {
slidingPaneLayout.addPanelSlideListener(this)
}
A classe SportsListOnBackPressedCallback
concluída é parecida com esta:
class SportsListOnBackPressedCallback(
private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen),
SlidingPaneLayout.PanelSlideListener{
init {
slidingPaneLayout.addPanelSlideListener(this)
}
override fun handleOnBackPressed() {
slidingPaneLayout.closePane()
}
override fun onPanelSlide(panel: View, slideOffset: Float) {
}
override fun onPanelOpened(panel: View) {
isEnabled = true
}
override fun onPanelClosed(panel: View) {
isEnabled = false
}
}
Registrar o callback
Para conferir o callback em ação, registre-o usando o agente OnBackPressedDispatcher
.
A classe de base de FragmentActivity
permite controlar o comportamento do botão "Voltar" usando o OnBackPressedDispatcher
. O OnBackPressedDispatcher
controla como os eventos do botão "Voltar" são enviados para um ou mais objetos OnBackPressedCallback
.
Adicione o callback usando o método addCallback()
. Esse método recebe um LifecycleOwner
. Isso garante que o OnBackPressedCallback
seja adicionado somente quando o LifecycleOwner
for Lifecycle.State.STARTED
. A atividade ou o fragmento também remove callbacks registrados quando o LifecycleOwner
associado é destruído, o que evita vazamentos de memória e o torna adequado para uso em fragmentos ou outros proprietários de ciclo de vida que tenham um ciclo mais curto.
O método addCallback()
também recebe a instância da classe de callback como o segundo parâmetro. Para registrar o callback, siga estas etapas:
- No arquivo
SportsListFragment
, na funçãoonViewCreated()
, logo abaixo da declaração da variável de vinculação, crie uma instância para oSlidingPaneLayout
e atribua o valor debinding.slidingPaneLayout
a ela.
val slidingPaneLayout = binding.slidingPaneLayout
- No arquivo
SportsListFragment
, dentro da funçãoonViewCreated()
, logo abaixo da declaração doslidingPaneLayout
, adicione este código:
// Connect the SlidingPaneLayout to the system back button.
requireActivity().onBackPressedDispatcher.addCallback(
viewLifecycleOwner,
SportsListOnBackPressedCallback(slidingPaneLayout)
)
O código acima usa addCallback()
, transmitindo o viewLifecycleOwner
e uma instância do SportsListOnBackPressedCallback
. Esse callback só fica ativo durante o ciclo de vida do fragmento.
- É hora de executar o app em um emulador com um perfil de smartphone e ver a funcionalidade personalizada do botão "Voltar" em ação.
10. Modo de bloqueio
Quando a lista e os painéis de detalhes se sobrepõem em telas menores, como em smartphones, os usuários podem deslizar nas duas direções por padrão, alternando livremente entre os painéis, mesmo quando não estão usando a navegação por gestos. Você pode bloquear ou desbloquear o painel de detalhes definindo o modo de bloqueio do SlidingPaneLayout
.
- No emulador com o perfil de telefone, tente deslizar o painel de detalhes para fora da tela.
- Você também pode deslizar no painel de detalhes. Tente fazer isso por conta própria.
- Esse não é um recurso desejável no app Sports. É recomendável bloquear o
SlidingPaneLayout
para impedir que os usuários deslizem para dentro ou fora usando gestos. Para implementar essa opção, defina olockMode
comoLOCK_MODE_LOCKED
abaixo da definição doslidingPaneLayout
no métodoonViewCreated()
:
slidingPaneLayout.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED
Para saber mais sobre os outros modos de bloqueio, consulte a documentação.
- Execute o app mais uma vez e observe que o painel de detalhes agora está bloqueado.
Parabéns por adicionar o SlidingPaneLayout
ao app.
11. Código da solução
O código da solução para este codelab está no projeto e no módulo mostrados abaixo.
- Navegue até a página do repositório do GitHub fornecida para o projeto.
- Verifique se o nome da ramificação corresponde ao especificado no codelab. Por exemplo, na captura de tela a seguir, o nome da ramificação é main.
- Na página do GitHub do projeto, clique no botão Code, que vai mostrar uma janela pop-up.
- Na janela pop-up, clique no botão Download ZIP para salvar o projeto no seu computador. Aguarde a conclusão do download.
- Localize o arquivo no computador. Geralmente ele é salvo na pasta Downloads.
- Clique duas vezes para descompactar o arquivo ZIP. Isso cria uma nova pasta com os arquivos do projeto.
Abrir o projeto no Android Studio
- Inicie o Android Studio.
- Na janela Welcome to Android Studio, clique em Open.
Observação: caso o Android Studio já esteja aberto, selecione a opção File > Open.
- No navegador de arquivos, vá até a pasta descompactada do projeto, que provavelmente está na pasta Downloads.
- Clique duas vezes nessa pasta do projeto.
- Aguarde o Android Studio abrir o projeto.
- Clique no botão Run
para criar e executar o app. Confira se ele é criado da forma esperada.