Retrieving values ​​from a list item when there are different layouts in the list

I have a list containing different xml layouts, each of which has a different view. I was wondering how I can get data from views inside the element that the user clicked on, inside the onItemClick method.

My list consists of several layouts, so I can’t know exactly which layout will be clicked when the onItemClick method is called. For example, one of the elements in the layouts in the list:

 // 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> 

As another layout, the list may include:

 // 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> 

Thus, I do not understand how to get data for all of these views for any layout in the list.

My previous attempt:

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

However, value in this case returns a string containing all the values ​​of all the views inside this element, for example: {caption=MobileNumber, value=07000123456} <<I can not do anything with this string if I do not try to figure it out using substring , which is unreliable at best, given that the user could create values.

This is my adapter to use ( Jeff Sharkey credit, I did not create this adapter):

 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; } } 

I am looking for a way to retrieve the values ​​of all the views inside an element. But the fact that the item that was clicked can be one of any layouts confuses me. Any ideas?

Here is an example of how I use this adapter in code:

 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(); } } 
+6
source share
2 answers

Here is a simple way - paste this into each of the xml views:

 android:onClick="someFunction" 

Then inside this someFunction do:

 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; } 
+1
source

My understanding here is that you have 3 types of elements:

  • Section heading (which is disabled thanks to the areAllItemsSelectable and isEnabled methods and therefore cannot be clicked)
  • Individual items
  • Double elements

You also have 2 sections, name and phone.

Elements from section 1 ( adapter.getItemViewType(position) == 1 ) are separate elements, and section 2 ( adapter.getItemViewType(position) == 2 ).

In both cases, your item object ( adapter.getItem(position) ) is declared as Map<String, ?> And even defined as Map<String, String> .

This means that you can overlay an element on a Map :

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

and then extract your value from the map using the ITEM_VALUE and ITEM_CAPTION .

+1
source

Source: https://habr.com/ru/post/951311/


All Articles