Como Utilizar o ListView para Selecionar Vários Itens no Android

Neste post vou demonstrar como trabalhar com um ListView que permite a seleção de um ou vários itens, e como tratar o retorno dos itens selecionados.

Criei um projeto onde são exibidas as regiões do Brasil (Figura 1) na Activity principal e quando selecionada uma região é apresentada uma Activity filha (Figura 2) com a relação de estados pertencentes àquela região, com um checkbox que permite a seleção ou não de cada estado (Figura 2).

listviewmultiplechoice4

Quando são selecionados um ou mais estados na Activity filha (Tela com a relação dos estados da região selecionada – Figura 2) e retornamos para a Activity principal (Figura 1) é apresentada uma mensagem com os estados que foram selecionados (Figura 3). No exemplo foi selecionada a região Sudeste na Activity Principal e os estados Minas Gerais, Rio de Janeiro e São Paulo.

listviewmultiplechoice5

No projeto foram criadas duas classes para representar as duas Activities. A primeira classe é a Main.java (Listagem 1)

Listagem 1
public class Main extends ListActivity implements OnItemClickListener {
    private String[] regiao = new String[]{
            "Centro-Oeste", "Nordeste", "Norte",
            "Sudeste", "Sul"};
    private final static int ACTIVITY_STATE = 1;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        setListAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, regiao));
        
        ListView listView = getListView();        
        listView.setOnItemClickListener(this);
    }
 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, 
            int position, long id) {
        String regiao = (String) parent.getItemAtPosition(position);
        
        Intent intent = new Intent(this, StateListActivity.class);
        intent.putExtra("estados", getEstados(regiao));        
        startActivityForResult(intent, ACTIVITY_STATE);
        
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
        // Verifica se o retorno veio da Activity chamada
        if (requestCode == ACTIVITY_STATE) {
            if (resultCode == RESULT_OK) {
                if (data != null) {
                    ArrayList<String> estados = data.getStringArrayListExtra("estados");
                    
                    StringBuilder message = new StringBuilder();
                    message.append("Estados selecionados:\n");
                    
                    for (int i = 0; i < estados.size(); i++) {
                            message.append(estados.get(i) + "\n");
                    }
                    
                    // Exibe o nome dos estados selecionados
                    Toast.makeText(this, message.toString(), Toast.LENGTH_SHORT).show();
                }
            }
        }                
        
    }
    
    private String[] getEstados(String regiao){
        
        if (regiao.equals("Centro-Oeste")) {
            return new String[]{
            "Goiás", "Mato Grosso", "Mato Grosso do Sul",
            "Distrito Federal"};
        }
        
        if (regiao.equals("Nordeste")) {
            return new String[]{
                    "Maranhão", "Piauí", "Ceará", "Rio Grande do Norte",
                    "Paraíba", "Pernambuco", "Alagoas", "Sergipe",
                    "Bahia};
        }
        
        if (regiao.equals("Norte")) {
            return new String[]{
                    "Acre", "Amazonas", "Roraima", "Rondônia",
                    "Pará", "Amapá", "Tocantins"};
        }
        
        if (regiao.equals("Sudeste")) {
            return new String[]{
                    "Minas Gerais", "Espírito Santo", "Rio de Janeiro",
                    "São Paulo"};
        }
        
        if (regiao.equals("Sul")) {
            return new String[]{
                    "Paraná", "Santa Catarina", "Rio Grande do Sul"};
        }
        
        return new String[] { "" };
    }
}

A classe Main.java constroi a tela Principal e trata o retorno dos dados recebidos da Tela dos Estados.

O método onCreate(Bundle) cria um ListView com o layout padrão do Android (android.R.layout.simple_list_item_1) com os dados obtidos da matriz regiao.

O método onItemClick(AdapterView<?>, View, int, long) é chamado quando uma região é selecionada no ListView. Neste método é armazenada a região selecionada na variável local regiao e a Activity dos Estados é exibida através da chamada do método startActivityForResult(intent, int) que exibe a Activity e aguarda o resultado dos estados selecionados quando a Activity chamada retornar para a Activity principal.

O método onActivityResult(int, int, Intent) é chamado quando a Activity de Estados retorna para a Activity Principal. Este método verifica se a Activity que retornou era a Activity esperada através da verificação do parâmetro requestCode, verifica se o resultado está correto através do parâmetro resultCode, obtêm os dados retornados através do parâmetro data e exibe uma mensagem indicando os estados selecionados na Activity de Estados.

O método getEstados(String) retorna uma matriz com os estados de acordo com a região informada no parâmetro regiao.

A segunda classe é a StateListActivity.java (Listagem 2).

Listagem 2
public class StateListActivity extends ListActivity implements OnItemClickListener {
    ListView listView;
    String[] estados;
    ArrayList<String> stateList;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Intent intent = getIntent();
        
        if (intent != null) {
            estados = intent.getStringArrayExtra("estados");
            
            // Exibe o listview com botão tipo checkbox
            setListAdapter(new ArrayAdapter<String>(this, 
                    android.R.layout.simple_list_item_multiple_choice,
                    estados));
            
            listView = getListView();
            
            // Desabilita o foco no item
            listView.setItemsCanFocus(false);
            
            // Configura o listview para permitir a seleção de
            // vários itens simultaneamente
            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
            
            listView.setOnItemClickListener(this);
        }
 
    }
 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, 
            int position, long id) {
        stateList = new ArrayList<String>();
        
        // Mapa de Booleans com a informação dos estados selecionados
        SparseBooleanArray status = listView.getCheckedItemPositions();
        
        // Limpa a lista anterior para manter atualizada
        // a última seleção
        stateList.clear();
        
        for (int i = 0; i < status.size(); i++) {
            if (status.valueAt(i) == true) {
                stateList.add((String)listView.getItemAtPosition
                        (status.keyAt(i)));
            }
        }
    }
    
    @Override
    public void onBackPressed() {
        // Verifica se algum estado foi selecionado
        if (stateList != null) {
            // Passa as informações dos estados selecionados para
            // a activity pai
            Intent intent = new Intent();
            intent.putStringArrayListExtra("estados", stateList);
            setResult(RESULT_OK, intent);
        }
        else
        {
            setResult(RESULT_CANCELED);            
        }
 
        super.onBackPressed();
    }
}

A classe StateListActivity.java é responsável por exibir a tela com a relação de estados e permite a seleção ou não de um ou mais estados.

O método onCreate(Bundle) utiliza o método getIntent() para obter a relação de estados que foi passada pela Activity principal (classe Main.java) e exibe a tela com o layout configurado para exibir um listview com botão tipo checkbox, configurado com a opção de selecionar vários itens simultaneamente.

O método onItemClick(AdapterView, View, int, long) é chamado quando um item do listview é selecionado. Neste método é utilizada a classe SparseBooleanArray que faz o mapeamento de boolean para integer e é utilizada para armazenar as informações de quais itens da relação de estados foi selecionado. Com o método valueAt(int) da classe SparseBooleanArray, obtemos o valor se true ou false para cada item, e com o método keyAt(int) obtemos a chave dentro da lista de itens. Esta chave é utilizada para determinar qual o estado que está com o status selecionado.

O método onBackPressed() é chamado quando é acionado o botão “Voltar” do emulador. Este método  passa as informações dos estados selecionados para a Activity principal.

Posts Relacionados: