I have a ListView , in the Item ListView there is a drop-down list ( Spinner ), there is also a "+" button with which the user can add new Items to the ListView. Suppose the user created two Items and selected certain values ​​in them in Spinner , when adding a new Item , the values ​​selected in the first two Items in Spinner get confused, I can’t understand how to save values ​​correctly and then display them when creating new Items .

There was an idea to save selected values ​​in ArrayList when onItemSelected into an array, but then it is not clear what to do if the user first selected one value and then changed it to another. Or maybe you need to use Expandable ListView ?

Code in Activity:

 public class ClaimWorkActivity extends Activity { ArrayList <String> workCount = new ArrayList<>(); WorksAdapter worksAdapter; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.claim_work_activity); workCount.add("1"); lvListWork = (ListView) findViewById(R.id.lvListWork); btnAdd =(Button) findViewById(R.id.btnAdd); worksAdapter = new WorksAdapter(this); lvListWork.setAdapter(worksAdapter); btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { workCount.add("1"); worksAdapter.addall(workCount); } }); worksAdapter.addall(workCount); } } } 

Adapter Code:

 public class WorksAdapter extends BaseAdapter { Context ctx; LayoutInflater lInflater; ArrayList<String> objects; private String [] workType = {"Work type 1", "Work type 2", "Work type 3", "Work type 4", "Work type 5"}; public WorksAdapter(Context context) { ctx = context; objects=new ArrayList<>(); lInflater = (LayoutInflater) ctx .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return objects.size(); } @Override public Object getItem(int position) { return objects.get(position); } @Override public long getItemId(int position) { return position; } public void addall(ArrayList<String> object){ objects.clear(); objects.addAll(object); notifyDataSetChanged(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = lInflater.inflate(R.layout.claim_work_item, parent, false); } ((TextView) view.findViewById(R.id.tvWorkNumber)).setText(String.valueOf(position+1)); //objects.get(position) Spinner spinnerClaimWorkName= (Spinner) view.findViewById(R.id.tvClaimWorkName); ArrayAdapter<String> adapterWorkType = new ArrayAdapter<String>(ctx, android.R.layout.simple_spinner_item, workType); adapterWorkType.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerClaimWorkName.setAdapter(adapterWorkType); spinnerClaimWorkName.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Log.d("Work Type", workType[position]); } @Override public void onNothingSelected(AdapterView<?> arg0) { } }); return view; } } 
  • 2
    In general, the algorithm for working with elements of an item that change the current state is the same . In the adapter, create a service array and save there all changes of the widget's state through its listener (in the spinner it is the number of the selected position), when outputting to getView() force the states to the element from this array, in the case of Spinner - the setSelection(position) method. Then this array can be picked up via the getter adapter in the activation or any other recipient that needs information on the elements selected in the list. - pavlofff
  • 2
    See also this answer , here is a slightly different algorithm - pavlofff
  • @pavlofff Ok, thanks! I will sort this out! - Lucky_girl

1 answer 1

I decided to redo the ListView with Spinner , in ExpandableListView , it seems to me that in this situation it is better suited, if only because I would need to use only one adapter. I installed OnClickListener on ExpandableListView and every time when the user selects the child position, I assign this value to the list on the basis of which headers are built and update the whole ExpandableListView . I also have a btnAdd button with which the user can add new Items, add a new element to the array on the basis of which headers are built and ExpandableListView updated.

Activity code:

 public class MainActivity extends Activity{ ClaimExpandableListAdapter listAdapter; ExpandableListView expListView; private Button btnAdd; List<String> listDataHeader; HashMap<String, List<String>> listDataChild; List<String> docTypes; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.claim_work_activity); expListView = (ExpandableListView) findViewById(R.id.elvMain); btnAdd =(Button) findViewById(R.id.btnAdd); prepareListData(); listAdapter = new ClaimExpandableListAdapter(this, listDataHeader, listDataChild); expListView.setAdapter(listAdapter); expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { listDataHeader.set(groupPosition, listDataChild.get( listDataHeader.get(groupPosition)).get( childPosition)); listDataChild.put(listDataHeader.get(groupPosition), docTypes); listAdapter.updateData(listDataHeader,listDataChild); listAdapter.notifyDataSetChanged(); return false; } }); } btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listDataHeader.add("Выберите тип работ"); listDataChild.put(listDataHeader.get(listDataHeader.size()-1), docTypes); listAdapter.updateData(listDataHeader,listDataChild); listAdapter.notifyDataSetChanged(); } }); } private void prepareListData() { listDataHeader = new ArrayList<String>(); listDataChild = new HashMap<String, List<String>>(); // Adding child data listDataHeader.add("Выберите тип работ"); // Adding child data docTypes = new ArrayList<String>(); docTypes.add("Work Type 1"); docTypes.add("Work Type 2"); docTypes.add("Work Type 3"); docTypes.add("Work Type 4"); docTypes.add("Work Type 5"); listDataChild.put(listDataHeader.get(0), docTypes); } } 

Adapter code:

 public class ClaimExpandableListAdapter extends BaseExpandableListAdapter { private Context _context; public List<String> _listDataHeader; // header titles // child data in format of header title, child title private HashMap<String, List<String>> _listDataChild; public ClaimExpandableListAdapter(Context context, List<String> listDataHeader, HashMap<String, List<String>> listChildData) { this._context = context; this._listDataHeader = listDataHeader; this._listDataChild = listChildData; } public ClaimExpandableListAdapter(Context context, List<String> listDataHeader) { this._context = context; this._listDataHeader = listDataHeader; } @Override public Object getChild(int groupPosition, int childPosititon) { return this._listDataChild.get(this._listDataHeader.get(groupPosition)) .get(childPosititon); } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final String childText = (String) getChild(groupPosition, childPosition); if (convertView == null) { LayoutInflater infalInflater = (LayoutInflater) this._context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = infalInflater.inflate(R.layout.claim_explist_item, null); } TextView txtListChild = (TextView) convertView .findViewById(R.id.lblListItem); txtListChild.setText(childText); return convertView; } @Override public int getChildrenCount(int groupPosition) { return this._listDataChild.get(this._listDataHeader.get(groupPosition)) .size(); } @Override public Object getGroup(int groupPosition) { return this._listDataHeader.get(groupPosition); } @Override public int getGroupCount() { return this._listDataHeader.size(); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { String headerTitle = (String) getGroup(groupPosition); if (convertView == null) { LayoutInflater infalInflater = (LayoutInflater) this._context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = infalInflater.inflate(R.layout.claim_list_group, null); } TextView tvWorkNumber = (TextView) convertView .findViewById(R.id.tvWorkNumber); TextView lblListHeader = (TextView) convertView .findViewById(R.id.tvClaimWorkName); lblListHeader.setTypeface(null, Typeface.BOLD); lblListHeader.setText(headerTitle); int displayPosition=groupPosition+1; tvWorkNumber.setText(String.valueOf(displayPosition)); return convertView; } @Override public boolean hasStableIds() { return false; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } public void updateData(List<String> groups, HashMap<String, List<String>> children) { this._listDataHeader = groups; this._listDataChild = children; } }