Autore Topic: [medio] ListView con layout personalizzato tramite un SimpleAdapter  (Letto 45827 volte)

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
+11
Livello di difficoltà: medio
Versione SDK utilizzata: >1.5
Link al file compresso del progetto eclipse: file in allegato

Quando vogliamo realizzare una listview con un layout personalizzato, ad esempio per una nostra classe personale, ci troviamo davanti diverse possibili implementazioni. Alcune di esse prevedono di estendere le classi BaseAdapter, ArrayAdapter o altre. In questo tutorial vorrei mostrarvi come è possibile creare una listview personalizzata utlizzando la classe SimpleAdapter, fornita dall'android SDK.


In una listview, vogliamo rappresentare una lista di oggetti appartenenti a questa classe:
Codice (Java): [Seleziona]
public class Person {
        private String name;
        private String surname;
        private int photoRes;
        public Person(String name, String surname, int photoRes) {
                super();
                this.name = name;
                this.surname = surname;
                this.photoRes = photoRes;
        }
        public String getName() {
                return name;
        }
        public String getSurname() {
                return surname;
        }
        public int getPhotoRes() {
                return photoRes;
        }
}


Ecco cosa vogliamo ottenere con una lista casuale di oggetti Persona:


ora per prima cosa definiamo un layout che mostra i dati di un  oggetto Persona su ogni singola riga della listview:
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="60dip"
        android:padding="5dip">


        <ImageView
                android:id="@+id/personImage"
                android:layout_width="50dip"
                android:layout_height="50dip"
        >
        </ImageView>


        <TextView
                android:text="Nome"
                android:layout_marginLeft="5dip"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:id="@+id/personName"
                android:layout_toRightOf="@id/personImage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"></TextView>
        <TextView
                android:text="Cognome"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="#6b71f1"
                android:id="@+id/personSurname"
                android:layout_alignLeft="@+id/personName"
                android:layout_alignParentBottom="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
        </TextView>
</RelativeLayout>

come possiamo ben osservare, questo layout definisce una ImageView per il campo photoRes della classe Persona, affiancato da 2 textview disposte una sopra l'altra per i campi Name e Surname, sempre della classe Persona.

il layout dell'activity non ha nulla di particolare:
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <ListView
                android:id="@+id/personListView"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
        </ListView>
</LinearLayout>

passiamo ora al codice java:

Codice (Java): [Seleziona]
public class Demo extends Activity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
       
        ArrayList<Person> personList=new ArrayList<Person>(); //lista delle persone che la listview visualizzerà
       
       
        Person [] people={
                        new Person("Anna","Falchi",R.drawable.creep_1),
                        new Person("Cameron", "Diaz", R.drawable.creep_2),
                        new Person("Jessica","Alba",R.drawable.creep_3),
                        new Person("Manuela","Arcuri",R.drawable.creep_4)};
       
        //riempimento casuale della lista delle persone
        Random r=new Random();
        for(int i=0;i<100;i++){
                personList.add(people[r.nextInt(people.length)]);
        }
       
       
       
        //Questa è la lista che rappresenta la sorgente dei dati della listview
        //ogni elemento è una mappa(chiave->valore)
        ArrayList<HashMap<String, Object>> data=new ArrayList<HashMap<String,Object>>();
       
       
        for(int i=0;i<personList.size();i++){
                Person p=personList.get(i);// per ogni persona all'inteno della ditta
               
                HashMap<String,Object> personMap=new HashMap<String, Object>();//creiamo una mappa di valori
               
                personMap.put("image", p.getPhotoRes()); // per la chiave image, inseriamo la risorsa dell immagine
                personMap.put("name", p.getName()); // per la chiave name,l'informazine sul nome
                personMap.put("surname", p.getSurname());// per la chiave surnaname, l'informazione sul cognome
                data.add(personMap);  //aggiungiamo la mappa di valori alla sorgente dati
        }
       
       
        String[] from={"image","name","surname"}; //dai valori contenuti in queste chiavi
        int[] to={R.id.personImage,R.id.personName,R.id.personSurname};//agli id delle view
       
        //costruzione dell adapter
        SimpleAdapter adapter=new SimpleAdapter(
                        getApplicationContext(),
                        data,//sorgente dati
                        R.layout.person_item, //layout contenente gli id di "to"
                        from,
                        to);
       
        //utilizzo dell'adapter
        ((ListView)findViewById(R.id.personListView)).setAdapter(adapter);
    }
}

Voilà :D

Spero che questo tutorial vi sia stato utile.



Un Saluto,
Qlimax
« Ultima modifica: 04 Giugno 2010, 16:26:56 CEST da Qlimax »

Offline blackgin

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1376
  • Respect: +161
    • Google+
    • blackgins
    • blackginsoft
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Sistema operativo:
    Mac OSX 10.8
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #1 il: 04 Giugno 2010, 09:18:00 CEST »
0
Davvero un'ottimo tutorial!
Postate il LogCat LogCat LogCat LogCat LogCat

Offline Vytek

  • Translate Team
  • Utente junior
  • **
  • Post: 125
  • Respect: +6
    • Mostra profilo
  • Dispositivo Android:
    Samsung S5
  • Sistema operativo:
    Windows 8.1
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #2 il: 04 Giugno 2010, 13:24:05 CEST »
0
Fantastico! E' proprio quello che cercavo di capire e far funzionare! Ringraziamento imperituro  ;-)

Un saluto...

P.S.: Se riesco ad avere tempo lo vorrei utilizzare nella mia applicazione open source...

Offline onire

  • Utente junior
  • **
  • Post: 52
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Dream G1, Samsung Galaxy S
  • Sistema operativo:
    Windows Xp
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #3 il: 04 Giugno 2010, 15:24:28 CEST »
0
Ciao complimenti.
Potresti spiegarmi meglio come funziona
Codice (Java): [Seleziona]
//Questa è la lista che rappresenta la sorgente dei dati della listview
        //ogni elemento è una mappa(chiave->valore)
        ArrayList<HashMap<String, Object>> data=new ArrayList<HashMap<String,Object>>();
       
       
        for(int i=0;i<personList.size();i++){
                Person p=personList.get(i);// per ogni persona all'inteno della ditta
               
                HashMap<String,Object> personMap=new HashMap<String, Object>();//creiamo una mappa di valori
               
                personMap.put("image", p.getPhotoRes()); // per la chiave image, inseriamo la risorsa dell immagine
                personMap.put("name", p.getName()); // per la chiave name,l'informazine sul nome
                personMap.put("surname", p.getSurname());// per la chiave surnaname, l'informazione sul cognome
                data.add(personMap);  //aggiungiamo la mappa di valori alla sorgente dati
        }

Non ho capito bene come è la struttura di data.

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #4 il: 04 Giugno 2010, 15:57:11 CEST »
0
data è un ArrayList di HashMap

vedila un po cosi:

Codice: [Seleziona]
ArrayList{

  HashMap:
  {image->2131}
  {name->"Manuela"}
  {surname->"Arcuri"}
  ,

  HashMap:
  {image->4353}
  {name->"Jessica"}
  {surname->"Alba"}

  ,

  HashMap:
  ...

  ,

  HashMap:
  ...
}

quindi in quel pezzo di codice, per ogni persona, costruisco un HashMap e lo inserisco in data.
Spero di essere stato esplicativo... ;-)


Offline onire

  • Utente junior
  • **
  • Post: 52
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Dream G1, Samsung Galaxy S
  • Sistema operativo:
    Windows Xp
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #5 il: 04 Giugno 2010, 16:20:21 CEST »
0
Ok, grazie, e l'associazione tra l'arraylist e la listview come avviene?

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #6 il: 04 Giugno 2010, 16:25:59 CEST »
0
Ok, grazie, e l'associazione tra l'arraylist e la listview come avviene?

Codice (Java): [Seleziona]
        String[] from={"image","name","surname"}; //dai valori contenuti in queste chiavi
        int[] to={R.id.personImage,R.id.personName,R.id.personSurname};//agli id delle view        
        //costruzione dell adapter
        SimpleAdapter adapter=new SimpleAdapter(
                        getApplicationContext(),
                        data,//sorgente dati
                        R.layout.person_item, //layout contenente gli id di "to"
                        from,
                        to);
       
        //utilizzo dell'adapter
        ((ListView)findViewById(R.id.personListView)).setAdapter(adapter);

Offline onire

  • Utente junior
  • **
  • Post: 52
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Dream G1, Samsung Galaxy S
  • Sistema operativo:
    Windows Xp
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #7 il: 04 Giugno 2010, 16:41:37 CEST »
0
Grazie, ma per me questo sdk è un po' troppo complicato  :-[ ho comprato anche il libro di Carli, ma con scarsissimi risultati.
Cmq, se volessi che quando clicco su una persona si apre una nuova pagina e nella quale in alto c'è la foto nome e cognome e sotto una listview con ulteriori informazione, un po' come avviene con i dettagli dei contatti in rubrica.
Quindi dovrei creare un nuovo layout tipo person_item che contenga anche la listview, giusto?


Offline Sandra

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows XP
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #8 il: 14 Giugno 2010, 17:01:53 CEST »
0
Grazie mille...é stato utilissimo!

Ora però ho un problema. La mia riga é formata da una TextView e da un bottone. Vorrei mostrare delle informazioni quando clicco sulla TextView.
Ho provato a mettere setOnItemClickListener() sulla ListView ma non reagisce mai. Funziona se faccio setOnTouchListener(), ma in questo modo non posso sapere su quale item ho cliccato.

Per la TextView ho specificato android:clickable="true".

Qualcuno può aiutarmi?
Grazie mille!!

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3487
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #9 il: 14 Giugno 2010, 17:11:46 CEST »
0
Qualcuno può aiutarmi?

Eventualmente apri un topic apposito e incolla dentro un po' di codice :)

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #10 il: 20 Giugno 2010, 18:26:04 CEST »
0
E' il mio primo post, ma seguo il forum da un po' in veste di neofita di Android. Ho trovato questo tutorial veramente molto utile come base di partenza per sperimentare un po'. Avrei una domanda su una variante che ho realizzato.

Ho aggiunto un button ADD sopra la listview, premendo ADD un elemento deve essere aggiunto alla base dati e poi la view aggiornata. Ho pensato di aggiungere un OnClickListener al button e all'evento OnClick creo una nuova HashMap, la aggiungo alla ArrayList e poi uso il notifyDataSetChanged dell'adapter. Per far funzionare il tutto sia l'arraylist che l'adapter sono "final".

E' corretto questo approccio?  :-)

Codice (Java): [Seleziona]
View.OnClickListener mAddListener = new OnClickListener() {
   public void onClick(View v) {
      HashMap<String,Object> personMap = new HashMap<String, Object>();

      personMap.put("image", R.drawable.creep_1);
      personMap.put("name", "Nuovo nome");
      personMap.put("surname", "Nuovo cognome");

      data.add(personMap);
      adapter.notifyDataSetChanged();
   }
};

Button btnAdd;
btnAdd = (Button) findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(mAddListener);
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #11 il: 22 Giugno 2010, 02:19:54 CEST »
0
si, dovrebbe essere corretto.  perchè,hai avuto problemi ?

per evitare i final, puoi dichiarare quegli oggetti a livello di classe.

Offline Biagio

  • Nuovo arrivato
  • *
  • Post: 1
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC Desire
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #12 il: 20 Luglio 2010, 12:48:16 CEST »
0
 :-)
Grazie veramente ben fatto, ottimo lavoro!

Biagio

Offline DX89B

  • Utente junior
  • **
  • Post: 121
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    HTC Desire
  • Play Store ID:
    Daniele Bonadiman
  • Sistema operativo:
    Mac OS X 10.6
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #13 il: 27 Luglio 2010, 18:43:15 CEST »
0
Un consiglio sull xml aggiungete il singleLine = true e scrollHorizzontal = false in questo modo

Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="60dip"
       android:padding="5dip">


        <ImageView
               android:id="@+id/personImage"
               android:layout_width="50dip"
               android:layout_height="50dip"
       >
        </ImageView>


        <TextView
               android:text="Nome"
               android:layout_marginLeft="5dip"
               android:textAppearance="?android:attr/textAppearanceLarge"
               android:id="@+id/personName"
               android:layout_toRightOf="@id/personImage"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:singleLine="true"
               android:scrollHorizontally="false"
               ></TextView>
        <TextView
               android:text="Cognome"
               android:textAppearance="?android:attr/textAppearanceMedium"
               android:textColor="#6b71f1"
               android:id="@+id/personSurname"
               android:layout_alignLeft="@+id/personName"
               android:layout_alignParentBottom="true"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:singleLine="true"
               android:scrollHorizontally="false"
         >
        </TextView>
</RelativeLayout>

altrimenti il layout si sfasa con stringhe troppo lunghe , non è propriamente un problema di questa listview perchè ha stringhe corte ma in una vostra implementazione può darvi problemi :) io ho risolto così

Offline max246

  • Utente junior
  • **
  • Post: 73
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    G1
  • Play Store ID:
    Christian
Re:[medio] ListView con layout personalizzato tramite un SimpleAdapter
« Risposta #14 il: 29 Luglio 2010, 16:29:48 CEST »
0
a me non resta a destra il testo :S Perchè?