ProgressBar dentro de uma ActionBar - Android
Autor: Márcio Júnior | Publicado: 2013-03-21T15:21:00-03:00







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:
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android" &gt;
    &lt;item
        android:id="@+id/action_atualizar"
        android:icon="@drawable/ic_menu_refresh"
        android:showAsAction="always"
        android:title="Atualizar"/&gt;
&lt;/menu&gt;


E na pasta res/layout o arquivo actionbar_atualizar.xml:
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;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" /&gt;


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&lt;Void, Void, Void&gt; {

  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.&nbsp; 


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.&nbsp; 


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!