2013-08-08 12 views
6

Ho una listview contenente diversi layout xml, ciascuno con viste differenti. Mi chiedevo come ottenere i dati dalle viste all'interno dell'oggetto su cui l'utente ha fatto clic, all'interno del metodo onItemClick.Recupera i valori dalla voce di elenco quando ci sono vari layout nell'elenco

La mia lista è composta da più layout, quindi non posso sapere con certezza quale layout debba essere premuto quando viene chiamato il metodo onItemClick. Per esempio, uno degli elementi di layout nel ListView è:

// list_item.xml 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

    <TextView 
     android:id="@+id/lblSub" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentTop="true" 
     android:padding="6dp" 
     android:layout_marginRight="4dp" 
     android:text="" 
     android:textColor="#FFFFFF" 
     android:textSize="18sp" /> 

    <TextView 
     android:id="@+id/lblMain" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:padding="6dp" 
     android:layout_marginLeft="4dp" 
     android:text="" 
     android:textColor="#FFFFFF" 
     android:textSize="18sp" /> 

</RelativeLayout> 

Dove come un altro layout nel listview potrebbe essere:

// list_item_name.xml 
<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <TextView 
     android:id="@+id/lblName" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:layout_marginLeft="4dp" 
     android:padding="4dp" 
     android:text="TextView" 
     android:textColor="#FFFFFF" 
     android:textSize="28sp" /> 

</RelativeLayout> 

Quindi io sono ad una perdita quanto a come ottenere i dati per tutte queste viste per qualsiasi layout all'interno del listview.

Il mio tentativo precedente era questo:

public void onItemClick(AdapterView<?> listView, View view, int position, long id) {    
    Object obj = adapter.getItem(position); 
    String value = obj.toString(); 
} 

Tuttavia value in questo caso, restituisce una stringa contenente tutti i valori di tutti i punti di vista all'interno di questa voce, per esempio: {caption=MobileNumber, value=0700} < < < non posso fare nulla con questa stringa a meno che non provi a selezionarla utilizzando substring, che è inaffidabile nel migliore dei casi considerando che i valori potrebbero essere stati creati dall'utente.

Questo è il mio adattatore in uso (credito per Jeff Sharkey, non ho creato questo adattatore):

public class SeparatedListAdapter extends BaseAdapter { 

    public final Map<String,Adapter> sections = new LinkedHashMap<String,Adapter>(); 
    public final ArrayAdapter<String> headers; 
    public final static int TYPE_SECTION_HEADER = 0; 

    public SeparatedListAdapter(Context context) { 
     headers = new ArrayAdapter<String>(context, R.layout.list_header); 
    } 

    public void addSection(String section, Adapter adapter) { 
     this.headers.add(section); 
     this.sections.put(section, adapter); 
    } 
    public void addSectionNoHeader(String section, Adapter adapter) { 
     this.sections.put(section, adapter); 
    } 

    public Object getItem(int position) { 
     for(Object section : this.sections.keySet()) { 
      Adapter adapter = sections.get(section); 
      int size = adapter.getCount() + 1; 

      // check if position inside this section 
      if(position == 0) return section; 
      if(position < size) return adapter.getItem(position - 1); 

      // otherwise jump into next section 
      position -= size; 
     } 
     return null; 
    } 

    public int getCount() { 
     // total together all sections, plus one for each section header 
     int total = 0; 
     for(Adapter adapter : this.sections.values()) 
      total += adapter.getCount() + 1; 
     return total; 
    } 

    public int getViewTypeCount() { 
     // assume that headers count as one, then total all sections 
     int total = 1; 
     for(Adapter adapter : this.sections.values()) 
      total += adapter.getViewTypeCount(); 
     return total; 
    } 

    public int getItemViewType(int position) { 
     int type = 1; 
     for(Object section : this.sections.keySet()) { 
      Adapter adapter = sections.get(section); 
      int size = adapter.getCount() + 1; 

      // check if position inside this section 
      if(position == 0) return TYPE_SECTION_HEADER; 
      if(position < size) return type + adapter.getItemViewType(position - 1); 

      // otherwise jump into next section 
      position -= size; 
      type += adapter.getViewTypeCount(); 
     } 
     return -1; 
    } 

    public boolean areAllItemsSelectable() { 
     return false; 
    } 

    public boolean isEnabled(int position) { 
     return (getItemViewType(position) != TYPE_SECTION_HEADER); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     int sectionnum = 0; 
     for(Object section : this.sections.keySet()) { 
      Adapter adapter = sections.get(section); 
      int size = adapter.getCount() + 1; 

      // check if position inside this section 
      if(position == 0) return headers.getView(sectionnum, convertView, parent); 
      if(position < size) return adapter.getView(position - 1, convertView, parent); 

      // otherwise jump into next section 
      position -= size; 
      sectionnum++; 
     } 
     return null; 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

} 

Sto cercando un modo di estrarre i valori di tutti i punti di vista all'interno della voce . Ma il fatto che l'elemento che è stato cliccato potrebbe essere uno qualsiasi di questi layout mi confonde. Qualche idea?

Ecco un esempio di come sto usando questo adattatore in codice:

SeparatedListAdapter adapter; 
Customer cust; 
ListView lvDetails; 

public Map<String,?> createDoubleItem(String title, String caption) { 
     Map<String,String> item = new HashMap<String,String>(); 
     item.put(ITEM_VALUE, title); 
     item.put(ITEM_CAPTION, caption); 
     return item; 
    } 

    public Map<String,?> createSingleItem(String name) { 
     Map<String,String> item = new HashMap<String,String>(); 
     item.put(ITEM_VALUE, name); 
     return item; 
    } 

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_view_customer); 

     Intent intent = getIntent(); 
     cust = Db.Functions.getCustomer(intent.getStringExtra("uuid")); 
     lvDetails = (ListView) findViewById(R.id.custdetails); 
     adapter = new SeparatedListAdapter(this); 
     lvDetails.setOnItemClickListener(new OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> listView, View view, int position, long id) { 
       Gen.popup("Item clicked"); 
      } 
     }); 

     // Name 
     List<Map<String,?>> name = new LinkedList<Map<String,?>>(); 
     if (cust.firstName == null && cust.lastName == null) 
      name.add(createSingleItem("Unnamed Customer")); 
     else 
      name.add(createSingleItem(
        ((cust.title != null) ? cust.title + " " : "") + 
        ((cust.firstName != null) ? cust.firstName + " " : "") + 
        ((cust.lastName != null) ? cust.lastName : ""))); 
     adapter.addSection("Name", new SimpleAdapter(this, name, R.layout.list_item_name, 
       new String[] { ITEM_VALUE }, 
       new int[] { R.id.lblName })); 
     // Phones 
     if ((cust.mobileNumber != null || cust.homeNumber != null || cust.workNumber != null) && SHOW_PHONES) 
     { 
      List<Map<String,?>> phone = new LinkedList<Map<String,?>>(); 
      if (cust.mobileNumber != null) 
       phone.add(createDoubleItem(cust.mobileNumber, "Mobile")); 
      if (cust.homeNumber != null) 
       phone.add(createDoubleItem(cust.homeNumber, "Home")); 
      if (cust.workNumber != null) 
       phone.add(createDoubleItem(cust.workNumber, "Work")); 
      adapter.addSection("Phone", new SimpleAdapter(this, phone, R.layout.list_item, 
        new String[] { ITEM_VALUE, ITEM_CAPTION }, 
        new int[] { R.id.lblSub, R.id.lblMain })); 
     } 
     lvDetails.setAdapter(adapter); 
     adapter.notifyDataSetChanged(); 
    } 
} 
+0

ottieni i dati dal tuo adattatore o dal tuo modello, non dalle tue visualizzazioni. – njzk2

+0

l'adattatore restituisce una stringa (le sezioni.keySet è un insieme di stringhe) o un adattatore (nel qual caso è possibile recuperare un elemento specifico di getItem su di esso di nuovo) – njzk2

+0

@ njzk2 Grazie per il chiarimento, ho paura di Sono ancora (abbastanza apparentemente) nuovo nello sviluppo di Android, saresti in grado di darmi un esempio sotto forma di risposta? –

risposta

1

Ecco un modo semplice - incolla questo in ciascuno dei xml Visualizzazioni:

android:onClick="someFunction" 

Poi all'interno di questa someFunction fare:

public void someFunction(View v){ 

switch (v.getId()){ 
case R.id.lblSub: 
    // This layout was clicked, do something about it 
    break; 

case R.id.lblMain: 
    // This layout was clicked, do something about it 
    break; 

} 
+0

Un metodo molto interessante - ci proverò ora. Ho ragione nell'assumere che questo si innesca solo se si premono le visualizzazioni stesse, ma ** non ** l'intera voce della lista? –

+0

Sì, questo funziona solo sulla vista concreta, tuttavia, penso che puoi metterlo anche in ListView e inserire il suo ID in un caso, ma poi non so quale clic potrebbe essere catturato, forse quello interno. – g00dy

+0

C'è un modo alternativo per farlo, quindi so quale * elemento dell'elenco * è stato premuto (e di conseguenza quale layout sta usando), invece di quale vista? –

1

La mia comprensione qui è che si dispone di 3 tipi di elementi:

  • Titolo della sezione (che sono disabili grazie ai metodi areAllItemsSelectable e isEnabled e quindi non può essere cliccato)
  • elementi singoli
  • articoli doppie

Hai anche a quanto pare 2 sezioni, Nome e Telefono.

Gli articoli della sezione 1 (adapter.getItemViewType(position) == 1) sono singoli articoli, mentre la sezione 2 (adapter.getItemViewType(position) == 2).

In entrambi i casi, l'oggetto item (adapter.getItem(position)) è dichiarato Map<String, ?> ed è addirittura definito come Map<String, String>.

Ciò significa che si può lanciare elemento a un Map:

Map<String, String> itemAsMap = (Map<String, String>) item; 

e poi prendere il vostro valore dalla mappa, utilizzando i tasti ITEM_VALUE e ITEM_CAPTION.

Problemi correlati