Как сохранить выбранные элементы ExpandableListView в ArrayList
У меня есть список пользователей внутри ExpandableListView
, теперь у меня есть 2 группы списка, теперь я пытаюсь создать ArrayList
, который будет добавлять данные, когда я нажимаю на пользователей, поэтому, если есть 2 группы школ, и я нажимаю на ученика каждого из них, у меня должно быть 2 позиции в моем массиве, по одному для каждой группы, содержащей ее соответствующих пользователей, моя проблема в том, что мой массив имеет 2 позиции, но он не отделяет студентов:
Я хочу это:
Школа A:
student1 выбран
student2
student3 выбран
Школа B:
student4
student5 выбран
В результате:
[0] → ученик 1,3 [1] → ученик 5
Вот что я пробовал до сих пор:
mGpsEscolas = new GPSEscolas();
mArrayEscolas = new ArrayList<GPSEscolas>();
aMap = new HashMap<String, GPSEscolas>();
ExpandList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(final ExpandableListView parent, View v, final int groupPosition, final int childPosition, final long id) {
ExpAdapter.setClicked(groupPosition, childPosition);
index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
parent.setItemChecked(index, true);
parent.setSelectedChild(groupPosition, childPosition, true);
parent.getChildAt(index);
IdAlunos = String.valueOf(mMainRest.mArrayList.get(groupPosition).getalunos().get(childPosition).getId_aluno());
IdEscola = String.valueOf(mMainRest.mArrayList.get(groupPosition).getId_escola());
ids_alunos.add(IdAlunos);
notificar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int groupCount = ExpandList.getExpandableListAdapter().getGroupCount();
for (int group = 1; group <= groupCount; group++) {
int gcount = ExpandList.getExpandableListAdapter().getChildrenCount(groupPosition);
mArrayEscolas = new ArrayList<GPSEscolas>();
for (int child = 1; child <= gcount; child++) {
mGpsEscolas.setIds_alunos(String.valueOf(IdAlunos).substring(1));
mGpsEscolas.setId_escola(Integer.valueOf(IdEscola));
mGpsEscolas.setLatitude(latitudeEscola);
mGpsEscolas.setLongitude(longitudeEscola);
mGpsEscolas.setDistancia(mMainRest.RaioEscola);
mArrayEscolas.add(mGpsEscolas);
if (ExpAdapter.isChildSelectable(groupPosition, childPosition)) {
aMap.put(ExpandList.getExpandableListAdapter().getChildId(group, child), mArrayEscolas);
}
}
}
}
});
return false;
}
});
Ответы
Ответ 1
Есть еще один путь. Вместо создания объекта-оболочки вы можете создать Map<group,List<child>> selected items
и добавить элементы в этот список примерно так же, прослушивая это событие:
mExpandableList.setOnChildClickListener(new OnChildClickListener() {
@Override public boolean onChildClick(ExpandableListView parent,
View v,int groupPosition, int childPosition, long id) {
//toggle selections code here
}
Итак, вот важная часть: (и полная работа github repo)
@Override
protected void onCreate(Bundle savedInstanceState) {
...// some init part
final MyAdapter adapter = new MyAdapter(schools, students);
listView.setAdapter(adapter);
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent,
View v, int groupPosition, int childPosition, long id) {
adapter.toggleSelection(groupPosition, childPosition);
adapter.notifyDataSetInvalidated();
return false;
}
});
}
У нас есть несколько вариантов размещения таких выбранных элементов, но в моем проекте я использую его в пользовательском классе адаптера. Нет никакой реальной потребности в адаптере custome, и в Activity можно поместить Map<G, List<C>> selectedItems;
и связанные функции (toggleSelection, isSelected, getSelectedItems), но нам все равно нужно выделить выбранные продажи, поэтому адаптер обычно является лучшим местом для его размещения.
private class MyAdapter<G, C> extends BaseExpandableListAdapter {
private List<G> groups;
private Map<G, List<C>> childMap;
private Map<G, List<C>> selectedItems;
public MyAdapter(List<G> groups, Map<G, List<C>> childMap){
this.groups = groups;
this.childMap = childMap;
this.selectedItems = new HashMap<>();
}
public boolean isSelected(int groupPosition, int childPosition){
G group = groups.get(groupPosition);
// getChild is adapter Fn and is the same as
// G group = groups.get(groupPosition)
// C child = childMap.get(group).get(childPosition);
C child = getChild(groupPosition, childPosition);
List<C> sel = selectedItems.get(group);
return sel != null && sel.contains(child);
}
public void toggleSelection(int groupPosition, int childPosition){
G group = groups.get(groupPosition);
C child = getChild(groupPosition,childPosition);
List<C> sel = selectedItems.get(group);
if (sel == null){
sel = new ArrayList<>(); // Lasy arrays creation
//can init all arrays in constructor and never check for nulls
selectedItems.put(group, sel);
}
if (sel.contains(child)) sel.remove(child);
else sel.add(child);
}
... // Adapter fns can find in git repo
![enter image description here]()
И преобразовать результат. Карта в список будет легкой задачей:
private ArrayList<String> selectedAsList(Map<String, List<String>> selectedItems){
ArrayList<String> result = new ArrayList<>();
for(List<String> students: selectedItems.values())
result.addAll(students);
return result;
}
или что-то подобное.
PS. Вы также можете играть с Map<group,List<child>>
. Это может быть практически любой
структуру данных, которую вы хотите. 2 массива или, может быть, только один массив, если у вас нет дубликатов в данных группы. Вы можете управлять им, ограничить количество выборов и так далее...
Ответ 2
Простое решение - создать новый класс SelectableObject
:
class SelectableObject<T>
{
boolean sel; T obj;
public SelectableObject<T>(T obj) { this.obj=obj; this.sel=false; }
public void select() { this.sel=true; }
public void deselect() { this.sel=false; }
public boolean isSelected() { return this.sel; }
public T getObject() { return this.obj; }
}
затем создайте свой ExpandableListView
следующим образом
public void setChildData()
{
ArrayList<SelectableObject<GPSEscolas>> child
= new ArrayList<SelectableObject<GPSEscolas>>();
child.add(new SelectableObject<GPSEscolas>(new GPSEscolas(..)));
..
childItems.add(child);
}
Затем нам нужно вызвать функцию onSelect
функции прослушивателя функции select
mExpandableList.setOnChildClickListener(new OnChildClickListener() {
@Override public boolean onChildClick(ExpandableListView parent,
View v,int groupPosition, int childPosition, long id) {
SelectableObject<GPSEscolas> item = (SelectableObject<GPSEscolas>)
parent.getExpandableListAdapter().getChild(groupPosition,childPosition);
if(!item.isSelected()) item.select();
else item.deselect();
..
})
Затем мы можем запросить выбранные элементы, такие как
public static ArrayList<GPSEscolas> getSelectedChildren(ExpandableListView listView)
{
ArrayList<GPSEscolas> list = new ArrayList<GPSEscolas>();
int count = listView.getGroupCount();
for (int group = 1; group <= count; group++)
{
int gcount = listView.getChildrenCount(position);
for (int child = 1; child <= gcount; child++)
{
SelectableObject<GPSEscolas> item = (SelectableObject<GPSEscolas>)
listView.getExpandableListAdapter().getChild(groupPosition,childPosition);
// Here is where you can see the solution beauty
if (item.isSelected())
{
list.add(item.getObject());
}
}
}
return list;
}