O ViewPager2 (link em inglês) é uma versão aprimorada da biblioteca ViewPager que oferece
funcionalidade aprimorada e aborda dificuldades comuns com o uso de ViewPager.
Caso seu app já use o ViewPager, leia esta página para saber mais sobre
migrando para ViewPager2.
Se você quiser usar ViewPager2 no seu app e não estiver usando
ViewPager, leia Deslizar entre fragmentos usando
ViewPager2 e Criar visualizações deslizáveis com
usando o ViewPager2 para mais
informações imprecisas ou inadequadas.
Benefícios da migração para o ViewPager2
O principal motivo para migrar é que ViewPager2 está recebendo dados
e não o ViewPager. No entanto, o ViewPager2 também oferece
e muitas outras vantagens específicas.
Compatibilidade com orientação vertical
O ViewPager2 oferece suporte à paginação vertical, além da horizontal tradicional.
paginação. É possível ativar a paginação vertical para um elemento ViewPager2 configurando o
Atributo android:orientation:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:orientation="vertical" />
Também é possível definir esse atributo de maneira programática usando o método setOrientation() (link em inglês) .
Suporte da direita para a esquerda
O ViewPager2 é compatível com paginação da direita para a esquerda (RTL, na sigla em inglês). A paginação RTL está ativada
de forma automática, quando apropriado, com base na localidade, mas também é possível
Para ativar a paginação RTL para um elemento ViewPager2, defina o
Atributo android:layoutDirection:
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layoutDirection="rtl" />
Também é possível definir esse atributo de maneira programática usando o método setLayoutDirection() (link em inglês) .
Coleções de fragmentos modificáveis
O ViewPager2 oferece suporte à paginação por uma coleção modificável de fragmentos,
chamar
notifyDatasetChanged()
para atualizar a IU quando a coleção subjacente é alterada.
Isso significa que seu app pode modificar dinamicamente a coleção de fragmentos em
ambiente de execução, e ViewPager2 exibirá corretamente a coleção modificada.
DiffUtil
O ViewPager2 foi criado no RecyclerView,
ou seja, ele tem acesso
Utilitário DiffUtil
. Isso gera vários benefícios, mas o mais importante é que
Os objetos ViewPager2 aproveitam nativamente as animações de alteração do conjunto de dados.
da classe RecyclerView.
Migrar seu app para o ViewPager2
Siga estas etapas para atualizar objetos ViewPager no seu app para ViewPager2:
Atualizar arquivos de layout XML
Primeiro, substitua os elementos ViewPager nos arquivos de layout XML por
Elementos ViewPager2:
<!-- A ViewPager element -->
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- A ViewPager2 element -->
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Atualizar as classes do adaptador
Ao usar ViewPager, foi necessário estender a classe do adaptador que
novas páginas fornecidas ao objeto. Dependendo do caso de uso, a ViewPager foi usada
três classes abstratas diferentes. O ViewPager2 usa apenas duas classes abstratas.
Para cada objeto ViewPager que você está convertendo em um objeto ViewPager2,
Atualize a classe do adaptador para estender a classe abstrata adequada da seguinte maneira:
- Quando
ViewPagerusarPagerAdapterpara paginar visualizações, useRecyclerView.AdaptercomViewPager2. - Quando
ViewPagerusouFragmentPagerAdapterpara paginar um pequeno, número fixo de fragmentos, o uso deFragmentStateAdaptercomViewPager2. - Quando
ViewPagerusouFragmentStatePagerAdapterpara percorrer uma número grande ou desconhecido de fragmentos, useFragmentStateAdaptercomViewPager2.
Parâmetros do construtor
Classes de adaptador baseadas em fragmentos herdadas de FragmentPagerAdapter ou
FragmentStatePagerAdapter sempre aceitam um único objeto FragmentManager.
como um parâmetro construtor. Quando você estende FragmentStateAdapter para um
ViewPager2, você tem as seguintes opções para o construtor
parâmetros:
- O objeto
FragmentActivityouFragmentem que oViewPager2reside. Na maioria dos casos, essa é a melhor opção. - Um objeto
FragmentManagere um objetoLifecycle.
As classes de adaptador baseadas em visualização herdadas diretamente de RecyclerView.Adapter fazem
não exigem um parâmetro construtor.
Modificar métodos
Suas classes de adaptador também precisam substituir métodos diferentes para ViewPager2.
do que com ViewPager:
- Em vez de
getCount(), modifiquegetItemCount(). Além do nome, esse método não muda. - Em vez de
getItem(), substituacreateFragment()na abordagem baseada em fragmento adaptador. Verifique se o novo métodocreateFragment()sempre fornece uma nova instância de fragmento sempre que a função é chamada em vez de reutilizar instâncias.
Resumo
Em resumo, para converter uma classe de adaptador ViewPager para uso com ViewPager2,
faça as seguintes alterações:
- Mude a superclasse para
RecyclerView.Adapterpara percorrer visualizações ouFragmentStateAdapterpara percorrer fragmentos. - Altere os parâmetros do construtor em classes de adaptador baseadas em fragmento.
- Modifique
getItemCount()em vez degetCount(). - Substituir
createFragment()em vez degetItem()no adaptador baseado em fragmento classes.
Kotlin
// A simple ViewPager adapter class for paging through fragments class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { override fun getCount(): Int = NUM_PAGES override fun getItem(position: Int): Fragment = ScreenSlidePageFragment() } // An equivalent ViewPager2 adapter class class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) { override fun getItemCount(): Int = NUM_PAGES override fun createFragment(position: Int): Fragment = ScreenSlidePageFragment() }
Java
// A simple ViewPager adapter class for paging through fragments public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlidePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return new ScreenSlidePageFragment(); } @Override public int getCount() { return NUM_PAGES; } } // An equivalent ViewPager2 adapter class private class ScreenSlidePagerAdapter extends FragmentStateAdapter { public ScreenSlidePagerAdapter(FragmentActivity fa) { super(fa); } @Override public Fragment createFragment(int position) { return new ScreenSlidePageFragment(); } @Override public int getItemCount() { return NUM_PAGES; } }
Refatorar interfaces do TabLayout
O ViewPager2 introduz alterações na integração do TabLayout. Se você
usa uma ViewPager com um objeto TabLayout para mostrar conteúdo horizontal.
guias para navegação, será necessário refatorar o objeto TabLayout para
com o ViewPager2.
A conta TabLayout foi dissociada do ViewPager2 e agora está disponível como parte do
Componentes do Material Design. Isso significa que, para usá-lo, você precisa adicionar
a dependência apropriada para seu arquivo build.gradle:
Groovy
implementation "com.google.android.material:material:1.1.0-beta01"
Kotlin
implementation("com.google.android.material:material:1.1.0-beta01")
Também é necessário mudar a localização do elemento TabLayout na hierarquia de
seu arquivo de layout XML. Com ViewPager, o elemento TabLayout é declarado como uma
filho do elemento ViewPager. mas com ViewPager2, o elemento TabLayout
é declarado diretamente acima do elemento ViewPager2, no mesmo nível:
<!-- A ViewPager element with a TabLayout -->
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.viewpager.widget.ViewPager>
<!-- A ViewPager2 element with a TabLayout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Por fim, atualize o código que anexa o objeto TabLayout ao
objeto ViewPager. Enquanto TabLayout usa o próprio setupWithViewPager()
para integrar com ViewPager, ele exige um TabLayoutMediator
para integração com ViewPager2.
O objeto TabLayoutMediator também processa a tarefa de gerar títulos de páginas
para o objeto TabLayout, o que significa que a classe do adaptador não precisa
substituir getPageTitle():
Kotlin
// Integrating TabLayout with ViewPager class CollectionDemoFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tabLayout = view.findViewById(R.id.tab_layout) tabLayout.setupWithViewPager(viewPager) } ... } class DemoCollectionPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { override fun getCount(): Int = 4 override fun getPageTitle(position: Int): CharSequence { return "OBJECT ${(position + 1)}" } ... } // Integrating TabLayout with ViewPager2 class CollectionDemoFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tabLayout = view.findViewById(R.id.tab_layout) TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = "OBJECT ${(position + 1)}" }.attach() } ... }
Java
// Integrating TabLayout with ViewPager public class CollectionDemoFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { TabLayout tabLayout = view.findViewById(R.id.tab_layout); tabLayout.setupWithViewPager(viewPager); } ... } public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { ... @Override public int getCount() { return 4; } @Override public CharSequence getPageTitle(int position) { return "OBJECT " + (position + 1); } ... } // Integrating TabLayout with ViewPager2 public class CollectionDemoFragment : Fragment() { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { TabLayout tabLayout = view.findViewById(R.id.tab_layout); new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText("OBJECT " + (position + 1)) ).attach(); } ... }
Suporte a elementos roláveis aninhados
ViewPager2 não oferece suporte nativo a visualizações de rolagem aninhadas nos casos em que o
visualização de rolagem tem a mesma orientação que o objeto ViewPager2 que contém
reimplantá-lo. Por exemplo, a rolagem não funcionaria para uma visualização de rolagem vertical dentro de uma
objeto ViewPager2 orientado verticalmente.
Para oferecer suporte a uma visualização de rolagem dentro de um objeto ViewPager2 com a mesma orientação, faça o seguinte:
você precisa chamar
requestDisallowInterceptTouchEvent() no objeto ViewPager2 quando você
esperar rolar o elemento aninhado. A rolagem aninhada do ViewPager2
exemplo (link em inglês) demonstra uma maneira de resolver esse problema com uma
layout de wrapper personalizado.
Outros recursos
Para saber mais sobre o ViewPager2, consulte os recursos adicionais a seguir.
Amostras
- Amostras do ViewPager2 no GitHub (em inglês)
Vídeos
- Virando a página: como migrar para o ViewPager2 (Conferência de Desenvolvedores Android '19)