I worked a lot to create **N-level expandableListView. I am able to make it to any level but my requirement is to maintain the state of opened groups even after scroll. I tried with multiple ways but still unsuccessful.
This Expandable listview is meeting with all company requirement other than this issue.
*This is one way, which i tried. I am able to save the states within objects but few subgroups are not getting displayed. *
I tried with onMeasure(width,height) method to maintain the height when dynamic generated list but still failed to get perfect one.
Also i went through a number of articles for the same.
Attached Screenshot of my working application..
Here is my Code.
public class ParentLevelAdapter extends BaseExpandableListAdapter {
private Context context;
private View convertView;
Account account;
private ArrayList<Model_Departments> list_departments;
public ParentLevelAdapter (Context context,
ArrayList<Model_Departments> list_departments, Account account) {
this.context = context;
this.list_departments = list_departments;
this.account = account;
}
public void updateList(Context context,
ArrayList<Model_Departments> list_departments, Account account) {
notifyDataSetChanged();
}
@Override
public Object getChild(int arg0, int arg1) {
return this.getChild(arg0, arg1);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent)
{
final SecondLevelExpandableListView subGroupListView;
SecondListView employeeLisView = null;
if (convertView == null) {
if (list_departments.get(groupPosition).hasSubGroups()) {
subGroupListView = new SecondLevelExpandableListView(
context);
subGroupListView.setGroupIndicator(null);
adap = new ParentLevelAdapter (context,
list_departments.get(groupPosition).subgroups,
account);
subGroupListView.setAdapter(adap);
return subGroupListView;
} else {
employeeLisView = new SecondListView(context);
employeeLisView.setAdapter(new EmployeeAdapter(context,
list_departments.get
(groupPosition).employee, account));
return employeeLisView;
}
} else {
if (list_departments.get(groupPosition).hasSubGroups()) {
if (convertView instanceof SecondLevelExpandableListView) {
subGroupListView = (SecondLevelExpandableListView) convertView;
subGroupListView.onMeasure(10000, 999999);
subGroupListView.setGroupIndicator(null);
adap = new ParentLevelAdapter (context,
list_departments.get(groupPosition).subgroups,
account);
subGroupListView.setAdapter(adap);
return subGroupListView;
} else {
subGroupListView = new SecondLevelExpandableListView(
context);
subGroupListView.setGroupIndicator(null);
adap = new ParentLevelAdapter (context,
list_departments.get(groupPosition).subgroups,
account);
subGroupListView.setAdapter(adap);
return subGroupListView;
}
} else {
if (convertView instanceof SecondListView) {
employeeLisView = (SecondListView) convertView;
employeeLisView.setAdapter(new EmployeeAdapter(context,
list_departments.get(groupPosition).employee,
account));
return employeeLisView;
} else {
employeeLisView = new SecondListView(context);
employeeLisView.setAdapter(new EmployeeAdapter(context,
list_departments.get(groupPosition).employee,
account));
return employeeLisView;
}
}
}
}
@Override
public int getChildrenCount(int groupPosition) {
// return list_departments.get(groupPosition).subgroups.size();
return 1;
}
@Override
public Object getGroup(int groupPosition) {
return list_departments.get(groupPosition);
}
@Override
public int getGroupCount() {
return list_departments.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertV, ViewGroup parent) {
convertView = convertV;
// Log.v("ParentAdapter GroupView ",list_departments.get(groupPosition).name);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.layout_icon_node, null);
TextView text = (TextView) convertView
.findViewById(R.id.node_value);
// text.setText("SECOND LEVEL");
text.setText(list_departments.get(groupPosition).name);
} else {
TextView text = (TextView) convertView
.findViewById(R.id.node_value);
text.setText(list_departments.get(groupPosition).name);
}
if (list_departments.get(groupPosition).isExpanded()) {
Log.i("Group Position=", groupPosition + " NAme="
+ list_departments.get(groupPosition).name);
((SecondLevelExpandableListView) parent)
.expandGroup(groupPosition);
}
/* code to save state for Group expand and collapse for individual objects*/
((SecondLevelExpandableListView) parent)
.setOnGroupExpandListener(new OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
// TODO Auto-generated method stub
list_departments.get(groupPosition).setExpanded(
true);
Log.i("Group", "Expand groupposition="
+ groupPosition);
Log.i("Group",
"Expand"
+ list_departments
.get(groupPosition).name);
}
});
((SecondLevelExpandableListView) parent)
.setOnGroupCollapseListener(new OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
// TODO Auto-generated method stub
list_departments.get(groupPosition).setExpanded(
false);
Log.i("Group", "Collapse groupposition="
+ groupPosition);
Log.i("Group",
"Collapse"
+ list_departments
.get(groupPosition).name);
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
My Pojo_Object:
public class Model_Departments implements Comparable<Model_Departments>{
public String name;
protected long parent_id;
private boolean isexpanded;
public boolean isExpanded() {
return isexpanded;
}
public void setExpanded(boolean isexpanded) {
this.isexpanded = isexpanded;
}
public ArrayList<Model_Departments> subgroups = new ArrayList<>();
public ArrayList<Model_Employees> employee = new ArrayList<>();
public Model_Departments(String department_name, long parent_id) {
this.name = department_name;
this.parent_id = parent_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getParent_id() {
return parent_id;
}
public void setParent_id(long parent_id) {
this.parent_id = parent_id;
}
public ArrayList<Model_Departments> getSubgroups() {
return subgroups;
}
public void setSubgroups(ArrayList<Model_Departments> subgroups) {
this.subgroups = subgroups;
}
public ArrayList<Model_Employees> getEmployee() {
return employee;
}
public void setEmployee(ArrayList<Model_Employees> employee) {
this.employee = employee;
}
public boolean hasEmployees() {
if (employee != null && employee.size() > 0)
return true;
else
return false;
}
public boolean hasSubGroups() {
if (subgroups != null && subgroups.size() > 0)
return true;
else
return false;
}
@Override
public int compareTo(Model_Departments another) {
if(this.hasSubGroups())
{
Collections.sort(this.subgroups);
}
return this.getName().compareTo(another.getName());
}
}
Model_Employee.java
public class Model_Employees implements Comparable<Model_Employees>{
public String name;
public Model_Employees(String name, String location) {
super();
this.name = name;
}
public Model_Employees() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Model_Employees another) {
return this.getName().compareTo(another.getName());
}
}
Thanks in advance.
I have the same issue before with N-level Expandable ListView, I use a trick that displays only one expand item. Although it does not look like the best solution for you, however, hope it helps!
// display only one expand item
mExpandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
int previousGroup = -1;
@Override
public void onGroupExpand(int groupPosition) {
if (groupPosition != previousGroup)
mExpandableListView.collapseGroup(previousGroup);
previousGroup = groupPosition;
}
});
and the same on secondLevelExpListView
UPDATE:
Another way you can try as the following (together with above setOnGroupExpandListener
):
public class CustomExpListView extends ExpandableListView
{
public CustomExpListView(Context context)
{
super(context);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
widthMeasureSpec = MeasureSpec.makeMeasureSpec(960, MeasureSpec.AT_MOST);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Then inside your ParentLevelAdapter
call this:
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final CustomExpListView secondLevelExpListView = new CustomExpListView(this.mContext);
String parentNode = (String) getGroup(groupPosition);
secondLevelExpListView.setAdapter(new SecondLevelAdapter(this.mContext, mListData_SecondLevel_Map.get(parentNode), mListData_ThirdLevel_Map));
secondLevelExpListView.setGroupIndicator(null);
secondLevelExpListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
int previousGroup = -1;
@Override
public void onGroupExpand(int groupPosition) {
if (groupPosition != previousGroup)
secondLevelExpListView.collapseGroup(previousGroup);
previousGroup = groupPosition;
}
});
return secondLevelExpListView;
}
If you don't want to use setOnGroupExpandListener
, then you should increase heightMeasureSpec
like this heightMeasureSpec = MeasureSpec.makeMeasureSpec(20000, MeasureSpec.AT_MOST);
Please note that I have only tested with 3-level expandable list view, you can read more at my answer at the following question:
How to add Three Level ListView in ExpandableListView in android
I have posted my full project to GitHub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With