Olá! Hoje vou mostrar como adicionar uma progressbar dentro de uma actionbar. Um bom exemplo de implementação deste recurso é o aplicativo do Gmail, onde você tem um item de menu (usado para atualizar seus e-mails) que quando clicado, é substituído pela progressbar até o procedimento ser concluído e então volta novamente a ser o item.
Para utilizar este recurso, a versão mínima requerida do sdk é a 11. Você também vai precisar dos ícones, que podem variar de acordo com o tema (baixe o pacote neste link). Para o exemplo estarei utilizando estes que são adequados para o tema Holo Light:
res/drawable-mdpi |
res/drawable-hdpi |
res/drawable-xhdpi |
Para começar salve os ícones nas respectivas pastas de acordo com as legendas nas imagens. Agora vamos precisar de dois arquivos xml, um para o item de menu e outro para a progressbar. Para o item, dentro da pasta res/menu, crie um arquivo chamado atualizar.xml com o seguinte conteúdo:
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_atualizar" android:icon="@drawable/ic_menu_refresh" android:showAsAction="always" android:title="Atualizar"/> </menu>
<?xml version="1.0" encoding="utf-8"?> <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_gravity="right" android:paddingRight="5dp" />
Para controlar quando vai aparecer o item ou a progressbar, a estrutura da classe deverá ser parecida com a que segue (odeio colar trechos muito grandes de código no site, mas paciência que vou explicar tudo lá embaixo):
import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends Activity { private boolean atualizando = false; private Menu mOptionsMenu; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getActionBar().setDisplayHomeAsUpEnabled(true); } @Override public void onBackPressed() { if (atualizando == true) { Toast.makeText(this, "Aguarde...", Toast.LENGTH_LONG).show(); } else { super.onBackPressed(); } } private void atualizar() { atualizando = true; setAtualizando(atualizando); new Operacao().execute(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); break; case R.id.action_atualizar: atualizar(); break; } return true; } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); mOptionsMenu = menu; getMenuInflater().inflate(R.menu.atualizar, menu); // atualizar(); return true; } public void setAtualizando(boolean atualizando) { if (mOptionsMenu == null) { return; } MenuItem atualizarItem = mOptionsMenu.findItem(R.id.action_atualizar); if (atualizarItem != null) { if (atualizando) { atualizarItem.setActionView(R.layout.actionbar_atualizar); } else { atualizarItem.setActionView(null); } } } class Operacao extends AsyncTask<Void, Void, Void> { Exception exception = null; @Override protected Void doInBackground(Void... params) { try { // Neste bloco vocẽ executa suas operações Thread.sleep(2000); } catch (Exception e) { exception = e; } return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); if (exception == null) { atualizando = false; setAtualizando(atualizando); } else { Toast.makeText(MainActivity.this, "Ocorreu um erro: " + exception.getMessage(), Toast.LENGTH_LONG).show(); } } } }
Bom, no começo temos duas variáveis: atualizando e mOptionsMenu. A primeira é simplesmente para identificar se a atualização está ocorrendo ou não em determinado momento. A segunda receberá o menu assim que ele for criado e permitirá a troca entre o item e a progressbar quando necessário.
Em seguida temos os seguintes métodos:
- onCreate: Não tem nada de especial além do comando getActionBar().setDisplayHomeAsUpEnabled(true), que adiciona o item "voltar" na actionbar.
- onBackPressed: É tratado se a atualização está ocorrendo e não permitirá voltar se for verdade.
- atualizar: Configura a barra com o setAtualizando e executa a tarefa que executará as operações de atualização. Falo sobre a classe que executa a tarefa logo abaixo.
- onOptionsItemSelected: Verifica qual item do menu foi clicado e executa a ação correspondente.
- onCreateOptionsMenu: A variável recebe o menu e caso queira que a Activity já inicie atualizando, basta descomentar o comando atualizar().
- setAtualizando: É o responsável por mostrar o item ou a progressbar na actionbar.
Por fim temos a classe interna Operacao, uma subclasse de AsyncTask que nos permite executar tarefas em background e atualizar a interface sem precisar de threads. Não vou entrar em detalhes sobre este tipo de classe, apenas saiba que o método doInBackground é usado para executar as operações (no exemplo chamei Thread.sleep(2000) apenas pra simular um procedimento rápido) e onPostExecute é executado quando doInBackground finalizar. E temos a variável exception que é usada pelos métodos para descobrir se a operação finalizou com sucesso.
Qualquer dúvida deixe nos comentários!