Migrando para ViewPager2

Nelson Glauber
3 min readFeb 14, 2020

O ViewPager é basicamente um gerenciador de layout que permite à aplicação exibir páginas de dados (normalmente) semelhantes, onde o usuário pode alternar entre essas páginas utilizando o gesto de swipe (deslizando horizontalmente) para esquerda e para direita.

Recentemente o Google apresentou o ViewPager2, que é parte integrante do Jetpack e que possui algumas melhorias em relação ao seu antecessor:

  • Permite o scroll vertical, bastando definir a propriedade android:orientation para "vertical";
  • Dá suporte a idiomas RTL (Right-to-Left) por meio da propriedade android:layoutDirection="rtl";
  • É possível modificar a listagem de fragments utilizado no adapter, similar ao que acontece na RecyclerView por meio da classe DiffUtil e com isso, as animações serão feitas automaticamente;

Para utilizar o ViewPager2 a primeira coisa é adicionar a dependência no build.gradle.

dependencies {
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation "com.google.android.material:material:1.1.0"
}

A dependência da biblioteca do Material Design é opcional, mas deve ser utilizada para exibir as abas do ViewPager2 por meio do componente TabLayout.

Em seguida devemos definir o adapter.

class MyFragmentAdapter(fa: FragmentActivity)
: FragmentStateAdapter(fa) {
override fun getItemCount(): Int = 4

override fun createFragment(position: Int): Fragment =
SimpleFragment.newInstance("Position: $position")
}

A classe herda de FragmentStateAdapter e recebe como parâmetro a activity que hospedará o ViewPager2. Ainda é possível criar o adapter utilizando o construtor que recebe como parâmetro um Fragment ou ainda um terceiro, que recebe o FragmentManager e um Lifecycle.

O método getItemCount indica quantas páginas serão exibidas. E o método createFragment, como próprio nome diz, é responsável por criar a instância do Fragment que será exibido na página correspondente ao parâmetro position.

O SimpleFragment usado nesse exemplo é um fragment simples. Seu código está listado a seguir:

class SimpleFragment: Fragment() {

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = TextView(requireContext()).apply {
text = arguments?.getString("text") ?: ""
}

companion object {
fun newInstance(s: String) =
SimpleFragment().apply {
arguments = Bundle().apply {
putString("text", s)
}
}
}
}

Em seguida, adicione o ViewPager2 no arquivo de layout.

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
app:tabIndicatorColor="@color/colorAccent"
app:tabTextColor="@android:color/white"
/>

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>

Aqui também foi adicionado o TabLayout que exibirá as abas.

Por fim, na activity, basta utilizar o código a seguir:

pager.adapter = MyFragmentAdapter(this)
TabLayoutMediator(tabs, pager) { tab, position ->
tab.text = "Aba $position"
}.attach()

Primeiramente foi criada uma instância do MyFragmentAdapter e atribuída ao ViewPager2 declarado no arquivo de layout. Em seguida, foi instanciado um TabLayoutMediator que será responsável por definir o título das abas do TabLayout.

Pronto! É isso que você precisa pra criar uma página com abas utilizando o ViewPager2. O resultado deve ficar como a seguir:

Exemplo do componente ViewPager2 em execução.

Como mencionei anteriormente, é possível utilizar um RecyclerView.Adapter para a ViewPager2. Vejamos o exemplo a seguir.

class MyAdapter: RecyclerView.Adapter<MyAdapter.PageHolder>() {

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): PageHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.layout_page, parent, false)
return PageHolder(view)
}

override fun getItemCount(): Int = 4

override fun onBindViewHolder(
holder: PageHolder,
position: Int
) {
holder.txtTexto.text = "Position: $position"
}

class PageHolder(root: View): RecyclerView.ViewHolder(root) {
val txtTexto = root.txtText
}
}

Se você já conhece uma RecyclerView deve perceber que ele é um adapter sem nada de especial. Mas com ele, podemos utilizar instâncias da classe View ao invés de Fragments no ViewPager2.

Atribuir o adapter ao ViewPager2 é idêntico ao apresentado anteriormente.

pager.adapter = MyAdapter()

A recomendação é que esse novo componente seja utilizado, uma vez que novas implementações serão realizadas apenas no ViewPager2. O ViewPager não será mais mantido e provavelmente será descontinuado (deprecated).

A maioria do conteúdo desse post foi retirado deste vídeo do Android Dev Summit: https://www.youtube.com/watch?v=lAP6cz1HSzA

Qualquer dúvida, deixe seu comentário ;)

4br4ç05
nglauber

--

--

Nelson Glauber

Android Developer. Google Developer Expert for Android/Kotlin. Author of “Dominando o Android”.