2012-03-13 5 views
5

Ho un ListView che contiene righe personalizzate. Questo riga personalizzata ha seguenti elementi UIModificare gli attributi di visualizzazione sulla selezione di voci di elenco

  1. ImageView imageView1, imageView2
  2. TextView textview1, textView2, textView3

Il requisito è quando la riga lista è SELEZIONATA ci sarebbe seguenti modifiche

imageView1 sfondo, il colore è cambiato

imageView1 il colore è cambiato

colore textview1, dimensioni e tipo di carattere è cambia colore

textview2, la dimensione viene modificata

colore textview3, la dimensione viene modificata

Quale sarebbe il modo migliore per progettare per questo?

AFAIK non possiamo applicare gli stili nel selettore. C'è un modo migliore per lavorare su questo piuttosto che gestire il codice java?

Abbiamo setOnItemSelectedListener che può essere impostato su un Listview che avrebbe seguenti metodi di callback:

i) onItemSelected

ii) onNothingSelected

Tuttavia non v'è alcun metodo callback che forniscono dettagli della oggetto che ha perso la concentrazione. È un posto migliore per fare i cambiamenti?

Grazie in anticipo.

+0

"AFAIK non è possibile applicare gli stili nel selettore. C'è un modo migliore di lavorare su questo invece di gestire il codice java?" Se non puoi farlo in un selettore, in quale altro modo potrebbe essere fatto, ma in Java? Forse potresti scavalcare gli attributi di stile indicati dal selettore predefinito? – nmr

+0

Gli stili possono essere applicati per modificare il colore di sfondo/disegnabile. Non sarebbe utile cambiare la dimensione del carattere. Inoltre ho bisogno di specificare il selettore per ciascuna delle viste figlio? Nel codice java come in, all'interno di getView(). –

risposta

2

Penso che quello che si vuole fare qui è creare un Compound Control. Puoi trovare un esempio nella directory SDK nella sottodirectory samples // ApiDemos (potresti voler scaricare il Android source se non hai queste directory).

Quello che vorrei fare è creare una classe che erediti da qualsiasi tipo di layout che si sta utilizzando per la riga personalizzata. Supponiamo che sia un LinearLayout per questo esempio. Nel costruttore della sottoclasse, è possibile gonfiare il layout da una risorsa, trovare le viste secondarie e collegarle a variabili di istanza e restituire LinearLayout al chiamante.

In questa sottoclasse, è possibile sovrascrivere setSelected e manipolare le viste secondarie nel modo desiderato.

Ecco un esempio di quello che sto descrivendo, sulla base di posta:

public class MyCustomLayout extends LinearLayout { 
    public ImageView imageView1; // These are public since you likely want 
    public ImageView imageView2; // to set them in your Adapter. 
    public TextView textView1; 
    public TextView textView2; 
    public TextView textView3; 

    public MyCustomLayout(Context ctxt) { 
     super(ctxt); 

     // The call below attaches the items in the mycustomlayout.xml file to this 
     // instance, which serves as the root element in the layout. 
     LayoutInflater.from(ctxt).inflate(R.layout.mycustomlayout, this, true); 

     imageView1 = (ImageView)findViewById(R.id.imageview1); 
     imageView2 = (ImageView)findViewById(R.id.imageview2); 
     textView1 = (TextView)findViewById(R.id.textview1); 
     textView2 = (TextView)findViewById(R.id.textview2); 
     textView3 = (TextView)findViewById(R.id.textview3); 
    } 

    @Override 
    public void setSelected(boolean selected) { 
     super.setChecked(selected); 
     if (selected) { 
      imageView1.setBackgroundColor(0xFFFF0000); // whatever color you want 
      // Do all the rest of the setting of your subviews here for 
      // the case when the row is selected. 
     } else { 
      imageView1.setBackgroundColor(0xFF000000); // whatever color you want 
      // Do all the rest of the setting of your subviews here for 
      // the case when the row is not selected 
     } 
    } 
} 

Ora, nel mycustomlayout.file XML, che si desidera utilizzare il tag <merge> in modo che non si crea un layout non necessaria:

<merge xmlns:android="http://schemas.android.com/apk/res/android"> 
    <ImageView 
     android:id="@+id/imageview1" /> 
    <ImageView 
     android:id="@+id/imageview2" /> 
    <TextView 
     android:id="@+id/textview1" /> 
    <TextView 
     android:id="@+id/textview2" /> 
    <TextView 
     android:id="@+id/textview3" /> 
</merge> 

Ho eliso tutta la configurazione dei subviews sopra, ovviamente, ma si dovrebbe ottenere l'idea di come per impostare il file XML. Puoi anche farlo in codice se non vuoi ingannare con XML e un LayoutInflater. Puoi guardare this helpful blog post sul blog dev di Android che parla di un caso simile verso la fine.

Quindi, nell'adattatore getView è possibile creare (o riciclare) istanze di MyCustomLayout, impostarle e lasciare che il framework si occupi di tenere traccia di quali file sono selezionate e quali non sono selezionate.

0

Ho un modo approssimativo ... ma è molto pesante processo ... una volta che un elemento è selezionato aggiorna il tuo listview ... solo per l'elemento selezionato dovrebbe mostrare quel tipo di carattere ecc ... e negozio l'ID dell'elemento selezionato in alcune variabili per abbinarlo mentre popola le visualizzazioni nell'adattatore ...

0

Prendere una variabile intera statica selectedPos a livello di attività.

in onItemSelezionato impostare tale variabile selectedPos = position e in onNothingSelected impostarlo su -1 e chiamare notifyDataSetChanged() per l'oggetto adattatore.

Ora nella classe di adattatori di ListView. condizione di scrivere in GetView come

if(position == selectedPos) 
{ 
    // set color and background to view 
} 

e non dimenticate di scrivere questo due metodi nella classe di adattatori,

@Override 
public int getItemViewType(int position) { 
return position; 
} 

@Override 
public int getViewTypeCount() { 
return _ArrayListObject.size(); 
} 
+0

Grazie soni. Tuttavia, ciò significherebbe ridisegnare di nuovo il listView per ogni elemento selezionato. Questo può essere evitato in qualsiasi modo? Anche notifyDataSetChanged() dovrebbe essere chiamato quando "i dati sottostanti sono stati modificati", che non è il caso qui. Non c'è supporto da parte del framework per gestire questo caso? –

+0

@khotmanish no .. :) :(.. Ho solo questa idea nella mia mente e penso che funzionerà per te .. – MKJParekh

0

Khotmanish,

Non sono sicuro di cosa si intende per il più efficiente modo. Ci sono molti modi che sono molto veloci, ma spesso dipende da ciò che sai in anticipo e da ciò che non sai.Si deve anche capire che le proprietà della vista dinamica sono pesantemente fraintese, ma altamente efficienti nonostante i miti popolari. Le persone di Google hanno fatto un ottimo lavoro nello sviluppo dell'interfaccia utente.

Se lo conosci in anticipo, puoi semplicemente creare un oggetto StateListDrawable per ciascuna vista e applicarlo a ciascuno mentre esegui l'adattatore.

Per costruire la vostra StateListDrawable, crearne uno:

StateListDrawable _drawStates; 

Poi, per ogni stato, aggiungere il drawable è necessario:

_drawStates.add(new int[] {android.R.attr.state_pressed}, _newImage); 

Questa è semplice come la seguente riga nel vostro GetView () metodo per il tuo adattatore:

v.setBackgroundDrawable(_drawStates); 

In alternativa, è possibile modificare gli sfondi in modo dinamico secondo la selezione. Questo può essere fatto in OnListItemClick(). Vedete, OnListItemClick() vi darà la visualizzazione esatta su cui è stato fatto clic. Una volta che avete questo, è possibile trovare il bambino dal suo id e modificare le sue proprietà e invalidate() esso. Uso questo trucco molto. Mi risparmia molta memoria, ma non sto facendo nulla di veramente intensivo sul processore. È possibile modificare quasi tutte le proprietà qui senza quasi alcuna elaborazione. Ecco un esempio:

@Override protected void onListItemClick(final ListView inList, final View v, final int atPos, final long rowID) 
{//Get the Child, set the properties 
    ImageView _img = (ImageView)(v.findViewById(R.id.app_package)); 
    _img.setBackgroundColor(myClickedColor); 
    _img.invalidate(); // <---- BEST Option 
// ... OR ... 
    v.invalidate();  // <---- 2nd Best Option 
// ... OR ... 
    inList.invalidate(); // <---- Last resort or specialized implementation 
} 

E 'importante notare che questa operazione ha dinamicamente alcuni avvertimenti quando si tratta di colori di sfondo. È NECESSARIO prelevare il bambino dalla vista selezionata ... Non da ListView. In secondo luogo, quando si cambiano i colori di sfondo, si stanno infatti modificando i Drawable di sfondo. Questo significa che tutte le altre proprietà "stateful" vanno via e devi cambiarle manualmente (se vuoi che inizi).

Ora, un approccio più popolare, ma un po 'meno flessibile è quello di creare il tuo StateListDrawable in XML. Ci sono un certo numero di risorse per imparare come farlo sul sito web degli sviluppatori Android.

Spero che questo aiuti, FuzzicalLogic

+0

Grazie per la tua risposta logica Fuzzical.Tuttavia StateListDrawable cambierebbe solo colore/drawable. t molto di aiuto per cambiare la dimensione del font.Inoltre sono più interessato allo stato onSelect piuttosto che allo stato onClicked (userei la trackball invece di onTouch). Quindi onListItemClick non mi aiuterà in questo modo :(. grazie per la tua breve risposta :) –

Problemi correlati