Uma das coisas boas de mexer a muito tempo com uma tecnologia, é que as pessoas sempre perguntam a você, mas obviamente, nem sempre você sabe a resposta. Meu amigo Rodrigo Jardim (a.k.a. Praieiro), me perguntou se eu conhecia o SlidingPaneLayout, e eu nunca tinha visto o dito cujo. Mas ele permite implementarmos um padrão de interface gráfica amplamente utilizada nas aplicações Android: menus laterais. Abaixo, coloquei um screenshot de duas "pequenas" aplicações que usam essa abordagem.
Como podemos notar, o Facebook e o GMail são dois bons exemplos de grandes aplicações que usam essa abordagem. Nesse post vou mostrar como dar os primeiros passos para construir um menu desse tipo. Vamos começar pelo arquivo de layout da aplicação, mostrado abaixo.
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sliding_pane_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- Menu Lateral --> <ListView android:id="@+id/left_pane" android:layout_width="280dp" android:layout_height="match_parent" android:layout_gravity="left" /> <!-- Conteúdo da tela --> <RelativeLayout android:id="@+id/rightPane" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff333333" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="MENU" android:onClick="abrirMenu"/> <ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/ic_launcher" /> </RelativeLayout> </android.support.v4.widget.SlidingPaneLayout>No SlidingPanelLayout temos apenas duas partes, a primeira (uma ListView) será o menu da aplicação. Enquanto que a segunda, será o conteúdo da tela em si. Abaixo temos o código da Activity.
public class MainActivity extends FragmentActivity implements OnItemClickListener, PanelSlideListener { private SlidingPaneLayout mSlidingLayout; private ListView mList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Colocando a Activity em tela cheia (opcional) requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mSlidingLayout = (SlidingPaneLayout) findViewById(R.id.sliding_pane_layout); mSlidingLayout.setPanelSlideListener(this); String[] opcoes = new String[] { "Opção 1", "Opção 2", "Opção 3", "Opção 4", "Opção 5" }; mList = (ListView) findViewById(R.id.left_pane); mList.setAdapter(new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1, opcoes)); mList.setOnItemClickListener(this); } // Evento de clique do botão public void abrirMenu(View v){ // Se estive aberto, feche. Senão abra. if (mSlidingLayout.isOpen()){ mSlidingLayout.closePane(); } else { mSlidingLayout.openPane(); } } @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { // TODO Tratar opções de Menu (ListView) aqui! } @Override public void onPanelClosed(View arg0) { // TODO Ao fechar o painel } @Override public void onPanelOpened(View arg0) { // TODO Ao abrir o painel } @Override public void onPanelSlide(View arg0, float arg1) { // TODO Enquanto o painel desliza } }O código acima é bem simples e está comentado.
O mais legal desse componente é que ao deslizar o dedo sobre a tela da esquerda para direita, o menu exibido (da direita para esquerda, ele fecha). Ou seja, o botão acima é opcional, mas indicado, como vemos nas aplicações em geral (como a do Facebook e Gmail) para facilitar a visualização do usuário.
Abaixo podemos ver nossa aplicações em execução com o menu lateral aberto.
É isso pessoal! Temos um menu no padrão de aplicações profissionais. Vale salientar que esse componente funciona em todas as versões do Android.
EDITADO em 29/11/2013
Várias pessoas me perguntaram (por email.... deixem os comentários aqui povo!) o que fazer com o clique do item da lista. O mais legal aqui é usar Fragments e sua stack. Ou seja, criar uma pilha de Fragments como o Android faz com as Activities. Ou seja, ao invés de irmos chamando Activities, chamamos Fragments e vamos empilhando-os no layout da direita.
Vamos ao exemplo... Crie a classe MeuFragment conforme abaixo:
public class MeuFragment extends Fragment { public static MeuFragment newInstance(String s){ Bundle args = new Bundle(); args.putString("texto", s); MeuFragment f = new MeuFragment(); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate( R.layout.meu_fragment, container, false); TextView txt = (TextView) layout.findViewById(R.id.textView1); txt.setText(getArguments().getString("texto")); return layout; } }O arquivo de layout do Fragment acima, só tem um RelativeLayout com um TextView centralizado (nada de mais, vocês conseguem :)
Agora, no clique de cada um dos itens, instanciamos esse fragment passando o texto da opção clicada.
@Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { String opcao = (String) mList.getAdapter().getItem(position); MeuFragment f = MeuFragment.newInstance(opcao); FragmentManager fm = getSupportFragmentManager(); // Opcional: isso removerá o fragment anterior // da pilha. fm.popBackStack(); fm.beginTransaction() .replace(R.id.rightPane, f, "frag1") .addToBackStack(null) .commit(); }O método addToBackStack vai adicionar o Fragment a uma pilha, dessa forma, ao clicar no botão back do aparelho, o fragment será removido automaticamente e anterior será exibido.
Qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber
Fonte: http://androidtrainningcenter.blogspot.com.br/2013/06/slidingpanelayout-android-making.html
18 comentários:
É isso ai Galuber...ficou muito legal!
Sensasional!
Esse glauber é um arrombado dos cavalos mesmo!
Pode ser dos póneis, que são menores? :)
Glauber! Obrigado pelo código!
Uma dúvida, nas opções do menu, eu tenho que usar a posição, certo? teria como você postar um exemplo usando esse menu, pra que a opção 5 seja o botão "sair" da aplicação? Seria de muita ajuda! Obrigado!
Oi Julio,
Não sei se entendi a dúvida, mas seria basicamente no onItemClick...
// Índice 4 = Opção 5
if (position == 4) finish();
4br4ç05,
nglauber
Ola muito bom amigo seu tutorial antes eu usava um framework mais esta solução e bem melhor um pergunra para colocar tb no lado esquerdo tipo tb nos dois lados como faria grato
Glauber, Parabens pelos posts, vc eh fera...
seguinte, minha tela principal, eh um mapa, quando deslizo o mapa para a direita, ta abrindo o MENU. tem como deixar essa opção habilitada SOMENTE para quando o usuario clicar no botao? Obrigado!!
Oi Luis,
Nesse caso, acho melhor você colocar um botão ou algo para ativar o sliding.
4br4ç05,
nglauber
Boa tarde.
Como seria pra colocar uma imagem pra cada menu ?
Oi Anônimo,
É normal a qualquer ListView. Você deve setar o adapter da ListView.
4br4ç05,
nglauber
Olá Glauber,
Tem também outra biblioteca que é a SlidingMenu. Muito boa mesmo e bem mais simples de se utilizar, pois não é necessário ficar definindo o widget nos XML. Trabalha muito nem em conjunto com a Sherlock, e é bem pequena, apenas quatro classes. Gosto mais dela devido ao efeito final, que ao abrir o menu lateral também "empurra" a actionbar, isso a lib da Google não faz. Fica a dica.
Olá Glauber, existe também a biblioteca SlidingMenu. Na minha opinião é bem melhor que a da Google, pois além de não ser necessário definir o widget no XML, ela também "empurra" a actionbar. Fica a dica. Valeu.
Como eu faço para ativar o slidingmenulayout apenas por um botão específico e bloqueálo se o usuário arrastar na tela, pois estou usando uma map.
Oi Pablo,
Na minha opinião, a melhor opção é o DrawerLayout...
http://developer.android.com/training/implementing-navigation/nav-drawer.html
Oi Le,
Acho que isso resolve seu problema.
http://stackoverflow.com/questions/17025957/disable-gesture-listener-on-drawerlayout
4br4ç05,
nglauber
Eu fiz tudo certinho aqui e tenho 5 opções no menu criado, e cada opção leva pra uma tela diferente. Como eu faria para associar cada item a tela correspondente?
Vlw, ótimo tutorial.
Oi Juninho,
O ideal é carregar um fragment dinamicamente para cada opção do seu menu.
http://developer.android.com/guide/components/fragments.html#Adding
Se o fragmento aberto, precisar exibir mais detalhes, aí você abre outra Activity.
4br4ç05,
nglauber
Como faço para cancelar o slider quando escorregar o dedo na tela, ou deixar somente ativo com o click do botão?
Oi Ricardo,
A recomendação é que seja usado o DrawerLayout e nele você pode usar o código abaixo:
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
Veja como implementar o DrawerLayout aqui:
http://developer.android.com/training/implementing-navigation/nav-drawer.html
4br4ç05,
nglauber
Postar um comentário