Autore Topic: Problema con ListView (probabile baco di Android ??)  (Letto 1150 volte)

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Problema con ListView (probabile baco di Android ??)
« il: 17 Maggio 2011, 13:02:45 CEST »
0
Salve a tutti, sono nuovo di questo forum e questo è il mio primo topic.

Vi espongo subito il problema.

Sto sviluppando una app (API level 8, Target Android 2.2), la quale deve visualizzare una lista di risultati.

Per questo ho creato una classe che estende una ListActivity, che dovrà visualizzare degli oggetti custom. Gli oggetti custom vengono mappati in una classe creata ex-novo che estende la classe ArrayAdapter e che successivamente viene passata all'actitvity mediante il metodo setListAdapter(arrayAdapter);

Fin qui tutto ok, non ci sono stati problemi, funziona tutto alla perfezione. I problemi sono sorti nel momento in cui è nata l'esigenza di distinguere i vari item della ListView
in base ad un particolare stato definito da una proprietà (boolean) dell'oggetto custom che viene visualizzato. Ho pensato di evidenziare questo stato colorando con un colore diverso la riga dell'item, effettuando questo controllo nel metodo getView del mio adapter e settando dinamicamente il colore della riga in base alla proprietà.

Funziona ma fino ad un certo punto, nel senso che è tutto regolare fino a che non incontra il primo item che presenta la riga di colore diverso, ma da quel momento in poi scorrendo la lista degli item in maniere casuale MAGICAMENTE si iniziano a evidenziare anche altre righe che non dovrebbero evidenziarsi.
Codice (Java): [Seleziona]
 public View getView(int position, View convertView, ViewGroup parent) {

      TextView cron, dest, ind, res, notificato;
      View v = convertView;
      if (v == null) {
         LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
               Context.LAYOUT_INFLATER_SERVICE);
         v = vi.inflate(R.layout.lista_atti_item, null);
      }

      final Atto atto = items.get(position);
     
      LinearLayout itemLayout = (LinearLayout) v.findViewById(R.id.item);
      notificato = (TextView) v.findViewById(R.id.notificato);
      cron = (TextView) v.findViewById(R.id.cronologico);
      dest = (TextView) v.findViewById(R.id.destinatario);
      ind = (TextView) v.findViewById(R.id.indirizzo);
      res = (TextView) v.findViewById(R.id.residenza);

      if ( atto.isModificato() )
      {
         Log.i(TAG_LOG, "L'atto " + atto.getDestinatario() + " ha l'esito settato!!");
         itemLayout.setBackgroundResource(R.color.celeste);
      }        
     
      itemLayout.setOnClickListener(new View.OnClickListener() {

         @Override
         public void onClick(View v)
         {
            Intent action = new Intent(getContext(),
                  AttoDetailActivity.class);

            Bundle bb = action.getExtras();
            if (bb == null)
               bb = new Bundle();

            bb.putSerializable("atto", atto);
            action.putExtras(bb);

            getContext().startActivity(action);

         }
      });

      if (atto != null)
      {
         cron.setText(atto.getCronologico());
         dest.setText(atto.getDestinatario());
         ind.setText(atto.getIndirizzo());
         res.setText(atto.getResidenza());
      }

      return v;
   }


Qualcuno sa spiegarmi che succede?   o_O
E' un baco oppure mi sfugge qualcosa? :-(

Ovviamente prima di scrivere in questo forum ci tengo a precisare che sono andato anche in debug e vi assicuro che è tutto lineare.
Non è la fame ma è l'ignoranza che uccide

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #1 il: 17 Maggio 2011, 13:37:32 CEST »
0
Non è un bug, è assolutamente normale in quanto stai facendo il recycle della convert view.
Per risolvere devi sempre impostare il colore, il questo modo:
Codice (Java): [Seleziona]
      if ( atto.isModificato() )
      {
         Log.i(TAG_LOG, "L'atto " + atto.getDestinatario() + " ha l'esito settato!!");
         itemLayout.setBackgroundResource(R.color.celeste);
      }else{
         itemLayout.setBackgroundResource(R.color.altro_colore);
      }
           

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #2 il: 17 Maggio 2011, 13:45:19 CEST »
0
Ricky` ti ha già dato la soluzione, io aggiungo un paio di osservazioni al codice:
- visto che stai ottimizzando la visualizzazione di una lista, usa anche un ViewHolder come suggerito qui: List14.java | Android Developers
- assolutamente non impostare il setOnClickListener dentro getView che ci perdi tutto l'efficienza, usa i metodi di ListView
- l'espressione atto != null è sempre vera, quindi inutile testarla (se non fosse cosi andresti in NullPointerException poco prima).

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #3 il: 17 Maggio 2011, 14:05:21 CEST »
0
Non è un bug, è assolutamente normale in quanto stai facendo il recycle della convert view.
Per risolvere devi sempre impostare il colore, il questo modo:
Codice (Java): [Seleziona]
      if ( atto.isModificato() )
      {
         Log.i(TAG_LOG, "L'atto " + atto.getDestinatario() + " ha l'esito settato!!");
         itemLayout.setBackgroundResource(R.color.celeste);
      }else{
         itemLayout.setBackgroundResource(R.color.altro_colore);
      }
           

Ok ci provo, anche se penso che impostare il colore nell'else sia superfluo. Non dovrebbe prendere automaticamente il colore di default?
Non è la fame ma è l'ignoranza che uccide

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #4 il: 17 Maggio 2011, 14:08:25 CEST »
0
Ok ci provo, anche se penso che impostare il colore nell'else sia superfluo. Non dovrebbe prendere automaticamente il colore di default?

Mi sa che non hai ben chiaro il funzionamento della variabile View convertView del metodo.

Leggi il link che ti ho passato.

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #5 il: 17 Maggio 2011, 14:08:54 CEST »
0
Ok ci provo, anche se penso che impostare il colore nell'else sia superfluo. Non dovrebbe prendere automaticamente il colore di default?

No perchè lui ricicla la view e potrebbe essere che quella che va a prendere in precedenza aveva settato l'altro colore.
Fidati che non è superfluo, parlo per esperienza.

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #6 il: 17 Maggio 2011, 14:11:49 CEST »
0
Funziona  :D

Però io continuo a pensare che sia un baco, in quanto penso che automaticamente debba prendersi il background di default (come ha sempre fatto d'altronde), e soprattutto è strano che cambia il colore in maniera random agli item che non soddisfanno la condizione.

Comunque grazie mille per la collaborazione!!
Non è la fame ma è l'ignoranza che uccide

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #7 il: 17 Maggio 2011, 14:13:30 CEST »
0
Non voglio fare lo sgarbato ma...

Leggi il link che ti ho passato.

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:Problema con ListView (probabile baco di Android ??)
« Risposta #8 il: 17 Maggio 2011, 14:15:54 CEST »
0
Però io continuo a pensare che sia un baco, in quanto penso che automaticamente debba prendersi il background di default (come ha sempre fatto d'altronde), e soprattutto è strano che cambia il colore in maniera random agli item che non soddisfanno la condizione.

Abbi pazienza, Ricky e Marcoduff te lo hanno spiegato, perchè non crederci?  :-)

Vedi questa parte di codice che hai scritto tu stesso?
Codice (Java): [Seleziona]
      if (v == null) {
         LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
               Context.LAYOUT_INFLATER_SERVICE);
         v = vi.inflate(R.layout.lista_atti_item, null);
      }

Significa che v può essere NULL o può non esserlo. Non sarà NULL quando viene riciclata una view precedente. Quando viene riciclata una view con colore diverso, se non lo rimetti come deve essere (codice postato da Ricky), ti rimarrà di quel colore.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #9 il: 17 Maggio 2011, 14:26:46 CEST »
0
Non voglio fare lo sgarbato ma...

Leggi il link che ti ho passato.

Ok, scusa non avevo visto il link. Ti consiglio di fare lo sgarbato se mi sfugge qualcosa  ;-)

Ora mi è chiaro, non avevo compreso bene il funzionamento del riciclo della view. Comunque ora sistemo meglio il codice.

Abbiate pazienza ma sono solo 2 settimane che sviluppo con Android. 8-)
Non è la fame ma è l'ignoranza che uccide

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #10 il: 17 Maggio 2011, 14:41:56 CEST »
0
Ricky` ti ha già dato la soluzione, io aggiungo un paio di osservazioni al codice:
- visto che stai ottimizzando la visualizzazione di una lista, usa anche un ViewHolder come suggerito qui: List14.java | Android Developers
- assolutamente non impostare il setOnClickListener dentro getView che ci perdi tutto l'efficienza, usa i metodi di ListView
- l'espressione atto != null è sempre vera, quindi inutile testarla (se non fosse cosi andresti in NullPointerException poco prima).

Quando dici che
Citazione
- assolutamente non impostare il setOnClickListener dentro getView che ci perdi tutto l'efficienza, usa i metodi di ListView
intendi che devo usare l'onclick sul tag del layout??
Non è la fame ma è l'ignoranza che uccide

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #11 il: 17 Maggio 2011, 14:47:07 CEST »
0
Quando dici che  intendi che devo usare l'onclick sul tag del layout??

No, l'onclick lo devi impostare all'elemento lista (ListView) e non ad ogni singolo elemento della lista (View della lista).

Un esempio è qui: List7.java | Android Developers

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #12 il: 17 Maggio 2011, 15:47:59 CEST »
0
No, l'onclick lo devi impostare all'elemento lista (ListView) e non ad ogni singolo elemento della lista (View della lista).

Un esempio è qui: List7.java | Android Developers

Ma se implemento l'ìinterfaccia OnItemSelectedListener come da esempio ed elimino View.OnClickListener sul custom adapter non riesco più a selezionare nessun item.

Se imposto l'onclick ad ogni singolo elemento quale metodo devo richiamare?? Devo creare io un metodo e farlo richiamare? Però a questo punto implementare l'interfaccia OnItemSelectedListener non mi serve più in quanto non utilizzo i metodi onItemSelected ed onNothingSelected?

Non è la fame ma è l'ignoranza che uccide

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #13 il: 17 Maggio 2011, 15:58:32 CEST »
0
Non ti seguo.

Perché non riusciresti più a selezionare nessun item? L'esempio List7.java funziona alla perfezioni e selezioni il singolo item!!!

Offline koreano

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Ubuntu 10.10
Re:Problema con ListView (probabile baco di Android ??)
« Risposta #14 il: 17 Maggio 2011, 16:08:59 CEST »
0
Non ti seguo.

Perché non riusciresti più a selezionare nessun item? L'esempio List7.java funziona alla perfezioni e selezioni il singolo item!!!

Questo è il mio list layout:
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" android:paddingLeft="4dp"
        android:paddingRight="4dp" android:background="#f2f2f2">
       
        <ListView android:id="@id/android:list"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="#f2f2f2"
                android:isScrollContainer="true"
                android:scrollbarStyle="insideOverlay"
                android:scrollbars="vertical"
                android:drawSelectorOnTop="false"  />
        <TextView
                android:id="@id/android:empty"
                android:text="@string/lista_verbali_empty"
                style="@style/Warning">
        </TextView>
</LinearLayout>

Come avevo implementato precedentemente per selezionare il mio item avevo aggiunto un OnClickListener sul linearLayout della riga:
Codice (Java): [Seleziona]
holder.itemLayout.setOnClickListener(new View.OnClickListener() {

                        @Override
                        public void onClick(View v)
                        {
                                Intent action = new Intent(getContext(),
                                                AttoDetailActivity.class);

                                Bundle bb = action.getExtras();
                                if (bb == null)
                                        bb = new Bundle();

                                bb.putSerializable("atto", atto);
                                action.putExtras(bb);

                                getContext().startActivity(action);
                        }
                });

Ora modificando il codice come da esempio List7, quindi implementando l'interfaccia OnItemSelectedListener, ed eliminando l'OnClickListener sul linearLayout non mi seleziona nulla, non fa più niente, non va nel metodo
Codice (Java): [Seleziona]
        @Override
        public void onItemSelected(AdapterView<?> parent, View v, int position, long id)
        {
                if ( position >= 0 )
                {
                        Atto atto = (Atto) parent.getItemAtPosition(position);
                       
                        Log.i(TAG_LOG, "Ho selezionato l'atto " + atto.getCronologico());
                        Toast.makeText(this, "Ho selezionato l'atto " + atto.getCronologico(), Toast.LENGTH_LONG).show();
                }              
        }

così come mi aspettavo.
Non è la fame ma è l'ignoranza che uccide