Android ExpandableListView Child-Auswahl speichern

Streeber

Aktives Mitglied
Hallo,

ich versuche ein Fragespiel mit ExpandableListView zu machen. Die Groups sind die Fragen und die Childs die Antwortmöglichkeiten, gefüllt wird alles dynamisch. Jetzt stecke ich allerdings beim Speichern der Antworten fest. Es soll ja maximal ein Child pro Group ausgewählt sein. Ich habe jetzt schon mehreres versucht (RadioGroups, BackgroundColor und Arraylist, Hashmap), aber so richtig funktionieren will nichts. Den Sourcecode für das ExpandableListView hab ich von einem Tutorial.

Java:
public class MyActivity extends Activity {

    private List<String> groupList, childList;
    private Map<String, List<String>> answerCollection;
    private ExpandableListView expListView;
    private ArrayList<Integer> chosenAnswers = new ArrayList<Integer>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        createGroupList();
        createCollection();

        setContentView(R.layout.main);
        expListView = (ExpandableListView) findViewById(R.id.expandableListView);
        final ExpandableListAdapter expListAdapter = new ExpandableListAdapter(this, groupList, answerCollection);
        expListView.setAdapter(expListAdapter);

        expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                long packedPosition;
                int packedPositionType;
                expListAdapter.addSelection(groupPosition, childPosition, v);
                answerCollection.put(expListAdapter.getChild(groupPosition, childPosition) + "", childList);
//                expListAdapter.getChildView(2, 2, false, v, parent).setBackgroundColor(Color.BLUE);
                System.out.println(parent.getSelectedItemPosition() + "    " + parent.getSelectedId());
                for (int i = 0; i < parent.getCount(); i++) {
                    packedPosition = parent.getExpandableListPosition(i);
                    packedPositionType = ExpandableListView.getPackedPositionType(packedPosition);
                    if (packedPositionType == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
//                        parent.getChildAt(i).setBackgroundColor(Color.BLACK);
                    }
                }

                for (int i = 0; i < parent.getChildCount(); i++) {
                    if (parent.getChildAt(i).equals(v)) { //Ausgewähltes Feld nicht einfärben
                        continue;
                    }
//                    parent.getChildAt(i).setBackgroundColor(Color.BLACK);
                }
                v.setBackgroundColor(Color.RED);
                final String selected = (String) expListAdapter.getChild(groupPosition, childPosition);
                Toast.makeText(getBaseContext(), selected, Toast.LENGTH_LONG).show();
                while (groupPosition > chosenAnswers.size()-1) { //Arraylist Stub-Elemente hinzufügen
                    chosenAnswers.add(-1);
                }
                System.out.println(groupPosition + " " + childPosition);
                chosenAnswers.set(groupPosition, childPosition); //Antwort abspeichern
//                expListView.collapseGroup(groupPosition);
                for (int i: chosenAnswers) { System.out.println(i); }
                return true;
            }
        });

    }

    public void addRadioButtons(int number) {
        System.out.println("\n \n \n" + findViewById(R.id.radiogroup));

        View parent = findViewById(R.id.expandableListView);
        parent.findViewById(R.id.radiogroup);
        setContentView(R.layout.child_item);
        ViewGroup  vwgroup = (ViewGroup) findViewById(R.id.radiogroup);
        for(int i = 0; i < 3; i++) {
            RadioButton rdbtn = new RadioButton(this);
            rdbtn.setId(i);
            rdbtn.setText("Radio " + rdbtn.getId());
            vwgroup.addView(rdbtn);
        }
    }

    private void createCollection() {

        String[] question1Answers = { "Gut", "Super", "Schlecht", "naja"};
        String[] question2Answers = { "Ja", "Nein", "Vielleicht"};
        answerCollection = new LinkedHashMap<String, List<String>>();

        for (String question : groupList) {
            if (groupList.get(0).equals(question))
                loadChild(question1Answers);
            else if (groupList.get(1).equals(question))
                loadChild(question2Answers);
            answerCollection.put(question, childList);
        }

    }

    private void loadChild(String[] answers) {
        childList = new ArrayList<String>();
        for (String answer : answers) {
            childList.add(answer);
        }
    }

    private void createGroupList() {
        groupList = new ArrayList<String>();
        grouplist.add("1");
        grouplist.add("2");
        grouplist.add("3");
        grouplist.add("4");
        grouplist.add("5");
        grouplist.add("6");
        Collections.shuffle(groupList);
        addRadioButtons(groupList.size());
    }
}

Ich versuche jetzt im OnClickListener die Antwort zu speichern und diese Rot einzufärben. Das mit dem Speichern funktioniert im Grunde ja auch mit der Arraylist, aber ich weiß nicht wie ich auf das richtige Child komme mit der group- und childPosition (bzw. wie ich alle Childs einer Group bekomme). Kann mir jemand weiterhelfen?
Vielen Dank schonmal!
 

dzim

Top Contributor
Ich hab das auch mal gemacht und war kurz davor, alles hinzuschmeissen, weil Expandable Lists in Android echt ein graus sind...
Wenn ich mal Zeit finde, such ich mal den Code raus und versuch es zu erklären. Mir ist das aber jetzt zu kompliziert, es mal schnell nebenbei versuchen es zu erklären. Sorry. (Zeit fehlt dafür)
 

Streeber

Aktives Mitglied
Ja wär super wenn du das machen könntest, ist auch nicht ganz so dringend, aber jetzt ganz von vorne anzufangen will ich irgendwie auch nicht.
 

dzim

Top Contributor
Also ich glaube, es ist schon mal wichtig zu erwähnen, dass ich einen eigenen BaseExpandableListAdapter implementiert habe.
Dort muss man die #getGroupView und #getChildView überschreiben. Da ich ein recht kompliziertes - oder sagen wir mal: spezielles - Set Up hatte, musste ich beides wirklich überschreiben. Dir würde vielleicht genügen für die Gruppen den Default zu verwenden.
Wichtig war dann in dem Aspekt also der ChildView:
Java:
		@Override
		public View getChildView(final int groupPosition, final int childPosition, final boolean isLastChild, View convertView, final ViewGroup parent) {
			
			final FilterTree item = tree.getChildren().get(groupPosition).getChildren().get(childPosition);
			
			switch (item.filter) {
			
			case SERIES:
				convertView = getSeriesChild(item, groupPosition, childPosition, convertView, parent);
				return convertView;
				
			case SERVER:
				convertView = getServerChild(item, groupPosition, childPosition, convertView, parent);
				return convertView;
				
			case ERROR:
				convertView = getRadioGroupChild(item, groupPosition, convertView, parent);
				return convertView;
				
			default: {
				convertView = getDefaultChild(item, groupPosition, convertView, parent);
				return convertView;
			}
			}
		}
Hinweis: Ich verwende für so Halb-Statische Geschichten (die Gruppen ändern sich ja nicht bei mir) gerne Enums und habe für die dann immer gleich noch den passenden Adapter implementiert - deine Fragen wären sicher dynamisch, da würde die Enum-Geschichte also wegfallen...
Java:
		private View getRadioGroupChild(final FilterTree item, final int groupPosition, View convertView, final ViewGroup parent) {
			
			convertView = mInflater.inflate(R.layout.simple_radiogroup_item_child, parent, false);
			
			RadioGroup rg = (RadioGroup) convertView.findViewById(R.id.radioGroup);
			
			for (FilterEnum errorFilter : getErrorValues()) {
				
				RadioButton rb = (RadioButton) mInflater.inflate(R.layout.simple_radio_item_child, rg, false);
				rb.setId(errorFilter.ordinal());
				
				String name = SpeedTestConstants.EMPTY_STRING;
				try {
					name = mContext.getString(errorFilter.filterName);
				} catch (Resources.NotFoundException e) {}
				rb.setText(name);
				
				rg.addView(rb);
			}
			
			if (ALL != item.filter && ERROR != item.filter) {
				rg.setEnabled(!selectedFilter.contains(ALL));
			}
			
			if (selectedErrorType != null) {
				rg.check(selectedErrorType.ordinal());
			} else {
				rg.check(ERROR_SHOW_ALL_RESULTS.ordinal());
			}
			
			rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
				@Override
				public void onCheckedChanged(RadioGroup group, int checkedId) {
					for (FilterEnum errorFilter : getErrorValues()) {
						if (errorFilter.ordinal() == checkedId) {
							selectedErrorType = errorFilter;
							break;
						}
					}
					if (updateParentHandler != null) {
						updateParentHandler.handle(selectedFilter, selectedSeries, selectedErrorType, selectedServer);
					}
				}
			});
			
			return convertView;
		}

Du siehst also: Ich war zu faul für ViewHolder (*autsch*, aber das ist die Wahrheit) und die Events auf dem Child muss man mit dem #setOnCheckedChangeListener auf der RadioGroup selbst abwickeln. Das Problem ist, dass die von dir verwendete #onChildClick nur Events der gesamten Gruppe abwickeln könnte - das wäre dann etwas umständlicher (#findView (RadionGroup), dann #getSelected (genauer Name ist mir gerade nicht mehr im Kopf)), aber nicht unmöglich.

Vielleicht bringt dir dieser Ansatz ja etwas...
 

Neue Themen


Oben