domingo, 16 de setembro de 2012

Paginação com Swipe no Android

Olá povo,

O versão 20 do plugin ADT (Android Development Toolkit) trouxe algumas novidades, entre elas, alguns templates de projetos que podemos optar na criação de um novo projeto Android. Hoje vou  explicar cada um desses templates e ver como utilizar o template que permite fazer uma paginação similar a do Google Play mostrada abaixo.


Note que a tela "Mais rentáveis" está em evidência, mas podemos notar que há uma opção a esquerda e outra a direita na parte superior. Esse é o intuito da paginação, que permitirá ao usuário exibir a próxima informação apenas deslizando para os lados. Vamos mostrar como fazer isso na sua aplicação.
Inicie a criação de um novo projeto e preencha os campos conforme abaixo e pressione Next.


Na segunda tela, há a opção de criarmos uma Activity em branco ou do tipo Mestre/Detalhe. A primeira cria uma Activity simples,  já a segunda, cria uma Activity que exibe uma listagem e os respectivos detalhes. Se a aplicação estiver executando em um tablet, a listagem e os detalhes de um item aparecem na mesma Activity, caso seja um smartphone, a listagem ficará em uma Activity e os detalhes serão exibidos em outra.
Selecione Blank Activity e clique em Next.
A próxima tela do assistente, solicita o nome da Activity que queremos criar, o nome do seu respectivo arquivo de layout e o título da Activity. Mas a informação mais interessante para nós aqui é o campo Navigation Type, que nos dá as seguintes opções:
A opção None não cria nenhuma opção pré-definida de navegação;
Selecionando Tabs, será criada uma estrutura básica de um Activity com abas usando uma ActionBar (que requer Android 4.1);
Tabs + Swipe é igual a anterior, mas será possível alternar entre as abas com o gesto de swipe (também requer Android 4.1);
Swipe Views + Title Strip permite alternar entre views usando swipe, e o título da view corrente é mostrado em um componente PageStrip;
A última opção é a Dropdown, que configura uma ActionBar onde o usuário poderá selecionar, através de um combobox, a tela que deseja abrir. Ao selecionar o item da lista, um Fragment será carregado (também requer Android 4.1)
Vamos utilizar a opção Swipe Views + Title Strip, pois funcionará em todas as versões do Android. Selecione-a e clique em Finish.
Uma coisa curiosa, é que para utilizar os templates acima, o assistente exige que seja selecionada a versão 4.0.1 do Android na primeira tela do assistente. Mas no caso do template que selecionamos, é possível fazer algumas alterações no projeto para que o mesmo funcione em aparelhos com versões anteriores. Tudo isso, graças a API de compatibilidade do Google (que fica na pasta libs do projeto).
1) Clique com o botão direito sobre o projeto e selecione Properties. Na tela que for exibida, selecione Android do lado esquerdo e em seguida, selecione Android 2.3 (API Level 10) e clique em OK.
2) A Activity dará erro, pois estamos importando duas classes que não existem no Android 2.3: android.app.ActionBar e android.app.FragmentTransaction. Remova esses dois imports.
3) Agora vá no AndroidManifest.xml e modifique o minSdkVersion para 10 (Android 2.3).
<uses-sdk
  android:minSdkVersion="10"
  android:targetSdkVersion="15"/>
4) Dará erro agora nas pastas values-v11, values-v14 e menu. Remova as três.
5) E para finalizar, remova o método onCreateOptionsMenu da sua Activity.

Pronto! Agora é só rodar no seu dispositivo 2.3, o resultado ficará como abaixo:
Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber

P.S.: Post relacionado: http://nglauber.blogspot.com.br/2011/09/pagescroll.html

11 comentários:

Francisco Monteiro disse...

Óptimo tutorial

Anônimo disse...

na hora de carregar estas fragments o programa carrega a atual a anterior e a sucessora. como fazer para dar um load apenas na fragment atual??

Nelson Glauber disse...

Oi Anônimo,

Tudo bem não carregarmos todos de uma vez, mas precisamos pelo menos a página anterior e a próxima, uma vez que podemos fazer swipe para página anterior ou posterior a qualquer momento.
Para controlar essa mudança de página, podemos ouvir o evento onPageChangeListener:

mViewPager.setOnPageChangeListener(
new OnPageChangeListener() {
public void onPageSelected(int arg0) {}
public void onPageScrolled(int arg0, float arg1, int arg2) {}
public void onPageScrollStateChanged(int arg0) {}
}
);

4br4ç05,
nglauber

Leonardo Melo Santos disse...

Glauber, acredito que "Swipe Views + Title Strip" não é suportado por todos. Apareceu a seguinte mensagem para mim: "Navigation Type "Swipe Views + Title Strip" requires a minimum SDK version of at least 11, and the current min version is 7". Estou equivocado em algo?

Nelson Glauber disse...

Oi Leonardo,

A mensagem está correta, pois o projeto que o assistente cria utiliza recursos só disponíveis no Android 3.0 (API Level 11). Se você notar, na imagem do post, estou usando a versão mínima como 4.0 e conforme coloquei no texto:
"Uma coisa curiosa, é que para utilizar os templates acima, o assistente exige que seja selecionada a versão 4.0.1 do Android"

4br4ç05,
nglauber

Deivison Francisco disse...

Valeuuu Glauber
Funcionou perfeitamente, agora vou continuar...

Cássio Oliveira disse...

Gostei do tutorial. Encontrei também uma forma que está na documentação como sendo uma forma mais apropriada de trabalhar para melhorar a compatibilidade de fragmento em aparelhos com sistema < 3.0:
http://stackoverflow.com/questions/6528691/fragments-in-android-2-2-1-2-3-2-0-is-this-possible

César Oliveira disse...

Boa tarde,

Seria bom se coloca-se uma opção para download do projecto.

Obrigado

Nelson Glauber disse...

Oi Cesar,

Acho que se você seguir os passos descritos não vai ter problemas em obter o código.

4br4ç05,
nglauber

Unknown disse...

Olá, Glauber, boa noite. Eu fiz o tutorial e tudo funcionou bem. Mas eu preciso atualizar o dados mostrados num dos fragments. E não consigo. A aplicação sempre mostra os mesmos dados. Como faço para colocar um botao num fragment e, com este botão atualizar os dados do outro fragment?
Obrigado e boa noite.

Nelson Glauber disse...

Olá Unknown,

Basicamente você tem que ter a referência dos dois fragments na Activity. Com isso você implementa um observer no Fragment1, a activity ouve esse evento e atualiza o Fragment2.
Por exemplo:

interface MeuEventoLegal {
void aconteceuAlgo();
}

class Fragment1 extends Fragment {
// obviamente deve haver um setMeuEventoLegal()...
private MeuEventoLegal listener;

private void noCliqueDoBotao(){
// Coloque o código que tem ser executado, e quando precisar
if (listener != null){
listener.aconteceuAlgo();
}
}
}

class MinhaActivity extends Activity implements MeuEventoLegal {
public void aconteceuAlgo() {
f2.atualizar();
}

// Em algum momento...
Fragment1 f1 = new Fragment1();
f1.setMeuEventoLegalListener(this);
}

Essa abordagem é mais complicada... Se preferir, você pode utilizar um BroadcastReceiver...

4br4ç05,
nglauber