Ordinare una ListView in Android

Mattepuffo's logo
Ordinare una ListView in Android

Ordinare una ListView in Android

Abbiamo visto come riempire una ListView in Android usando dati in formato JSON.

Solo che la lista risulta "statica" nel senso che come ci arriva la leggiamo, e non possiamo ordinarla.

Qui vediamo proprio questo: come ordinare una ListView simulando una tabella con righe e colonne.

Partiamo dalla Activity principale:

public class MainActivity extends Activity {
    
    private TextView txtTitolo = null;
    private TextView txtCreazione = null;
    private ListView listView = null;
    private SimpleAdapter adapter = null;
    private ArrayList> list = new ArrayList>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setLista();
        txtTitolo = (TextView) findViewById(R.id.h_titolo);
        txtCreazione = (TextView) findViewById(R.id.h_creazione);
        txtTitolo.setOnClickListener(new ListSort(list, "titolo", adapter));
        txtCreazione.setOnClickListener(new ListSort(list, "creazione", adapter));
    }
    
    private void setLista() {
        try {
            listView = (ListView) findViewById(R.id.lista_articoli);
            JSONArray jsonArray = new JSONArray(JsonFile.read(path + "blog_articoli.json"));
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jo = jsonArray.getJSONObject(i);
                HashMap map = new HashMap();
                map.put("id", jo.getString("id"));
                map.put("titolo", jo.getString("titolo"));
                map.put("creazione", jo.getString("creazione"));
                map.put("modifica", jo.getString("modifica"));
                map.put("count", jo.getString("count"));
                list.add(map);
            }
            adapter = new SimpleAdapter(this, list, R.layout.rows,
                    new String[] { "titolo", "creazione", "modifica", "count" },
                    new int[] { R.id.titolo, R.id.creazione, R.id.modifica, R.id.count });
            listView.setAdapter(adapter);
        } catch (JSONException e) {
        } catch (Exception e) {
        }
    }

}

Tralascio tutta la parte del recupero dati, partendo che l'abbiate già messa a punto (quella parte non cambia).

Abbiamo due campi: titolo e creazione; e ci sono vari riferimenti ai componente del layout che adesso vediamo.

Questo il main_layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_dark" >

        <TextView
            android:id="@+id/h_titolo"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:height="30dip"
            android:paddingLeft="5dp"
            android:text="@string/titolo"
            android:textSize="12sp"
            android:width="115dp" />

        <TextView
            android:id="@+id/h_creazione"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:height="30dip"
            android:text="@string/creazione"
            android:textSize="12sp"
            android:width="80dip" />

    </LinearLayout>

    <ListView
        android:id="@+id/lista_articoli"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

Il LinearLayout interno rappresenta la "testata" della tabella, e le TextView sulle quali abbiamo impostato il sorting al tocco.

Questo invece il layout delle righe:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:paddingBottom="6dip"
    android:paddingLeft="5dp"
    android:paddingTop="4dip" >

    <TextView
        android:id="@+id/titolo"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:width="115dip"
           android:textSize="12sp" />

    <TextView
        android:id="@+id/creazione"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:width="80dip"
        android:textSize="12sp" />

</LinearLayout>

A questo punto vediamo la classe per il sorting:

public class ListSort implements View.OnClickListener {
    
    private boolean c = true;
    private ArrayList> list;
    private String campoToSort;
    private SimpleAdapter adapter;
    
    public ListSort(ArrayList> list, String campoToSort, SimpleAdapter adapter) {
        this.list = list;
        this.campoToSort = campoToSort;
        this.adapter = adapter;
    }

    @Override
    public void onClick(View v) {
        if (c) {
            c = false;
            Collections.sort(list, new ListComparator(campoToSort));
        } else {
            c = true;
            Collections.reverse(list);
        }
        adapter.notifyDataSetChanged();
    }
    
}

La classe implementa OnClickListener, per interecettare il tocco dell'utente, e il costruttore prende tre parametri: la lista, il campo da ordinare, l'adapter a cui notificare il cambiamento (in modo che graficamente il cambiamento si veda subito e non ad un nuovo lancio della app).

Questa invece la classe che si occupa effettivamente di comparare gli elementi e ordinarli:

public class ListComparator implements Comparator> {
    
    private String campo;
    
    public ListComparator(String campo) {
        this.campo = campo;
    }

    @Override
    public int compare(HashMap lhs, HashMap rhs) {
        return lhs.get(campo).compareToIgnoreCase(rhs.get(campo));
    }

}

La classe implementa Comparator, e ne abbiamo già parlato qua (anche se qua parliamo di file e directory, ma il concetto di base è lo stesso).

Se avete fatto tutto bene, dovreste trovarvi con un layout simile a una tabella, con la possibilità di ordinare il tutto cliccando sull'intestazione.

Ciao!


Condividi

Commentami!