terça-feira, 15 de março de 2016

ViewPager sem FragmentPagerAdapter + Indicator

Olá povo,

Resolvi escrever esse post porque toda vez que eu preciso disso tenho que procurar na internet. Não que seja difícil de achar, mas me vi na obrigação moral de fazer :)
Quando utilizamos o ViewPager, normalmente estamos fazendo alguma tela de abas ou algo similar. Nesse caso é recomendado fazer com que cada aba/página seja um Fragment. Mas se não houver nenhuma lógica nessas páginas, criar um fragment pode ser desnecessário.
Posso dar como exemplo aquelas telas de boas-vindas que mostram um breve tutorial de como utilizar a aplicação, onde cada passo é uma página com as instruções. Nesse caso, utilizar um layout (definido em um arquivo de layout) para cada página seria o suficiente, e não precisaríamos de Fragment para tal.
Vamos ver como fazer isso,  começando pelo arquivo de layout a seguir.

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.viewpagerindicator.CirclePageIndicator
        android:id="@+id/indicator"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:background="@color/colorPrimary"/>
</LinearLayout>

Esse arquivo possui um ViewPager e um CirclePageIndicator (criado por Jake Wharton) que servirá para exibir um indicador da página atual. Para utiliza-lo, basta adicionar no build.gradle a dependência do componente.
dependencies {
    ...
    compile 'com.android.support:appcompat-v7:23.2.0' 
    compile 'com.github.JakeWharton:ViewPagerIndicator:2.4.1@aar'
}
Vejamos agora o código que cria as páginas do ViewPager.
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = (ViewPager)findViewById(R.id.viewpager);
        viewPager.setAdapter(new ViewSimplesAdapter());

        CirclePageIndicator indicator = 
                (CirclePageIndicator)findViewById(R.id.indicator);
        indicator.setViewPager(viewPager);
    }

    private class ViewSimplesAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return 3;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            int layout;
            if (position == 0){
                layout = R.layout.layout_pagina1;
            } else if (position == 1){
                layout = R.layout.layout_pagina2;
            } else {
                layout = R.layout.layout_pagina3;
            }
            View view = LayoutInflater.from(container.getContext())
                    .inflate(layout, container, false);
            container.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, 
                                Object object) {
            container.removeView((View)object);
        }
    }
}
A classe ViewSimplesAdapter herda de PagerAdapter e nela, temos o método getCount() que retorna a quantidade páginas que iremos exibir e mais três métodos:
  • isViewFromObject() - basicamente determina se uma View está relacionada com o objeto retornado pelo método instantiateItem().
  • instantiateItem() carrega o arquivo de layout da página específica. Perceba que a View carregada é adicionada ao ViewGroup recebido como parâmetro e é retornada pelo método.
  • destroyItem() vai ser responsável por destruir os itens criados. É importante ressaltar que o ViewPager mantém no máximo três páginas ativas: a que está sendo exibida, a anterior e a posterior.
Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber

6 comentários:

Fabio Queiroz disse...

Salve.
Por algum motivo, não está encontrando a Lib.

Meu repositório:

allprojects {
repositories {
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
maven { url "http://dl.bintray.com/rubengees/maven" }
maven { url "http://dl.bintray.com/populov/maven" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}

}



Error:A problem occurred configuring project ':app'.
> Could not find library.aar (com.viewpagerindicator:library:2.4.1).
Searched in the following locations:
https://jcenter.bintray.com/com/viewpagerindicator/library/2.4.1/library-2.4.1.aar

Alguma idéia?

Nelson Glauber disse...

Oi Fábio,

Tenta tirar o jcenter(). Funcionou comigo.

4br4ç05,
nglauber

Fabio Queiroz disse...

Se eu tiro o jcenter, ele não encontra outras Libs que uso.
Se vou no Project Structure > Project, e retiro o jcenter de lá, não encontra a lib Otto (vou trocar por EventBus em breve), mas não reclama da viewpageindicator. Se adiciono mavenCentral, ai não acha ela no repositorio do Maven.

Error:A problem occurred configuring project ':app'.
> Could not find library.aar (com.viewpagerindicator:library:2.4.1).
Searched in the following locations:
https://repo1.maven.org/maven2/com/viewpagerindicator/library/2.4.1/library-2.4.1.aar

Rapaz... que sinuca de bico.
:D

Fabio Queiroz disse...

O engraçado é que, em outro projeto que tinha em outra estrutura de projeto (workspace), já tinha usado/testado ela (em outra versão).

Fabio Queiroz disse...

Achei uma solução viável:

trocar
compile 'com.viewpagerindicator:library:2.4.1@aar'

por
compile 'com.github.JakeWharton:ViewPagerIndicator:2.4.1@aar'

:D

Nelson Glauber disse...

Oi Fábio,

Obrigado pela dica! Post atualizado ;)

4br4ç05,
nglauber