ExpandableListView实现Listview折叠工具

时间:2022-02-28 19:42:35
 

ExpandableListView使用解析这是一个比较老的控件工具   这个和ListView差不多



1.先来一个二级列表实现  主函数
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">


<ExpandableListView
android:id="@+id/tree_view_simple"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</ExpandableListView>


</LinearLayout>




2.然后创建实体类
/**
*
* 班级实体类
* Created by MH on 2016/6/16.
*/
public class Classes {


// 班级名
public String name;


// 班级中的学生列表
public List<String> students;

}






3.设置适配器     这里可能有一些不明白  
  • getGroupCount():获取一级条目的数量。
  • getChildrenCount():获取二级条目的数量。
  • getGroupView():获取一级条目的对应布局。
  • getChildView():获取二级条目对应的布局。

  • setAdapter()设置适配器

public class ClassesExpandableListViewAdapter extends BaseExpandableListAdapter {


// 班级的集合
private List<Classes> classes;

// 创建布局使用
private Activity activity;


public ClassesExpandableListViewAdapter(List<Classes> classes, Activity activity) {
this.classes = classes;
this.activity = activity;
}

@Override
public int getGroupCount() {
// 获取一级条目的数量 就是班级的大小
return classes.size();
}

@Override
public int getChildrenCount(int groupPosition) {
// 获取对应一级条目下二级条目的数量,就是各个班学生的数量
return classes.get(groupPosition).students.size();
}

@Override
public Object getGroup(int groupPosition) {
// 获取一级条目的对应数据 ,感觉没什么用
return classes.get(groupPosition);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
// 获取对应一级条目下二级条目的对应数据 感觉没什么用
return classes.get(groupPosition).students.get(childPosition);
}

@Override
public long getGroupId(int groupPosition) {
// 直接返回,没什么用
return groupPosition;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
// 直接返回,没什么用
return childPosition;
}

@Override
public boolean hasStableIds() {
// 谁知道这个是干什么。。。。
return false;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

// 获取对应一级条目的View 和ListView 的getView相似

return getGenericView(classes.get(groupPosition).name);
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

// 获取对应二级条目的View 和ListView 的getView相似
return getGenericView(classes.get(groupPosition).students.get(childPosition));
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
// 根据方法名,此处应该表示二级条目是否可以被点击 先返回true 再讲
return true;
}


/**
* 根据字符串生成布局,,因为我没有写layout.xml 所以用java 代码生成
*
* 实际中可以通过Inflate加载自己的自定义布局文件,设置数据之后并返回
* @param string
* @return
*/
private TextView getGenericView(String string) {

AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);

TextView textView = new TextView(activity);
textView.setLayoutParams(layoutParams);

textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);

textView.setPadding(40, 20, 0, 20);
textView.setText(string);
textView.setTextColor(Color.RED);
return textView;
}

}




4.主函数代码
public class MainActivity extends AppCompatActivity {
private ExpandableListView listview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 查找控件
listview = findViewById(R.id.tree_view_simple);
// 初始化数据
List<Classes> classesList = new ArrayList<>();
for(int i = 1 ;i<3;i++) {
Classes classes = new Classes();
classes.name = "计算机"+i+"班";
List<String> list = new ArrayList<>();
list.add("mm");
list.add("dd");
classes.students = list;
classesList.add(classes);
}
// 构造适配器
ClassesExpandableListViewAdapter adapter = new ClassesExpandableListViewAdapter(classesList,this);
// 设置适配器
listview.setAdapter(adapter);
}
}




当然二级到这里就结束了    下面开始三级列表实现

5.一样创建一个实体类
/**
* 大学实体类
* Created by MH on 2016/6/16.
*/
public class College {

// 大学名
public String name;

// 班级列表
public List<Classes> classList;
}




6.在主函数写一个方法
/**
* 初始化数据
*/
private void initData() {


College college = new College();

college.name = "科技大学";

List<Classes> classesList = new ArrayList<>();

for(int i = 1 ;i<3;i++) {
Classes classes = new Classes();

classes.name = "计算机"+i+"班";

List<String> list = new ArrayList<>();

list.add("mm");
list.add("dd");
classes.students = list;

classesList.add(classes);
}

college.classList = classesList;


colleges = new ArrayList<>();
colleges.add(college);

}





7.现在数据如下列所示
 
科技大学 
  • 计算机1班 
    • mm
    • dd
  • 计算机2班 
    • mm
    • dd

8.理解
ExpandableListView实现Listview折叠工具




9.外层适配器创建
/**
*
* 外层ExpandListView 适配器的实现
* Created by MH on 2016/6/16.
*/
public class SimpleExpandableListViewAdapter extends BaseExpandableListAdapter {


// 大学的集合
private List<College> colleges;

private Activity activity;


public SimpleExpandableListViewAdapter(List<College> colleges, Activity activity) {
this.colleges = colleges;
this.activity = activity;
}

@Override
public int getGroupCount() {
return colleges.size();
}

@Override
public int getChildrenCount(int groupPosition) {
// 很关键,,一定要返回 1
return 1;
}

@Override
public Object getGroup(int groupPosition) {
return colleges.get(groupPosition);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
return colleges.get(groupPosition).classList.get(childPosition);
}

@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}

@Override
public boolean hasStableIds() {
return false;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

return getGenericView(colleges.get(groupPosition).name);
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

// 返回子ExpandableListView 的对象 此时传入是该父条目,即大学的对象(有歧义。。)

return getGenericExpandableListView(colleges.get(groupPosition));
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}

private TextView getGenericView(String string) {
AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);

TextView textView = new TextView(activity);
textView.setLayoutParams(layoutParams);

textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);

textView.setPadding(40, 20, 0, 20);
textView.setText(string);
textView.setTextColor(Color.RED);
return textView;
}


/**
* 返回子ExpandableListView 的对象 此时传入的是该大学下所有班级的集合。
* @param college
* @return
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public ExpandableListView getGenericExpandableListView(College college){
AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);

CustomExpandableListView view = new CustomExpandableListView(activity);

// 加载班级的适配器
ClassesExpandableListViewAdapter adapter = new ClassesExpandableListViewAdapter(college.classList,activity);

view.setAdapter(adapter);

view.setPadding(20,0,0,0);
return view;
}
}


代码依然一大串,但其实和之前写的ClassExpandableListViewAdapter都差不多一样,主要有以下几点区别:

  • getChildrenCount() 返回1.
  • getChildView() 返回的是ExpandableListView对象。
  • getGenericExpandableListView(): 添加了获取ExpandableListView对象的方法。
可能在这里,观察仔细的会发现 getGenericExpandableListView() 中创建的是 CustomExpandableListView 对象,该对象是我自定义的。很多人可能都遇到过, ScrollView 嵌套 ListView ListView 显示不全。同样在这里也出现了, 子ExpandableListView 同样显示不全,所以自定义解决这个问题。




10.解决上面所述问题
/**
*
* 自定义ExpandableListView 解决嵌套之下显示不全的问题
* Created by MH on 2016/6/16.
*/
public class CustomExpandableListView extends ExpandableListView {


public CustomExpandableListView(Context context) {
super(context);
}

public CustomExpandableListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public CustomExpandableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 解决显示不全的问题
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2
, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}





11.最后在主函数里面写

public class SimpleExpandListViewActivity extends AppCompatActivity {


private ExpandableListView listview;

private List<College> colleges;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_tree_view_simple);

initData();

// 查找控件
listview = ((ExpandableListView) findViewById(R.id.tree_view_simple));


SimpleExpandableListViewAdapter adapter = new SimpleExpandableListViewAdapter(colleges,this);

// 设置适配器
listview.setAdapter(adapter);
/*
// 初始化数据
List<Classes> classesList = new ArrayList<>();

for(int i = 1 ;i<3;i++) {
Classes classes = new Classes();

classes.name = "计算机"+i+"班";

List<String> list = new ArrayList<>();

list.add("mm");
list.add("dd");
classes.students = list;

classesList.add(classes);
}*/

// 构造适配器
// ClassesExpandableListViewAdapter adapter = new ClassesExpandableListViewAdapter(classesList,this);





}

/**
* 初始化数据
*/
private void initData() {


College college = new College();

college.name = "科技大学";

List<Classes> classesList = new ArrayList<>();

for(int i = 1 ;i<3;i++) {
Classes classes = new Classes();

classes.name = "计算机"+i+"班";

List<String> list = new ArrayList<>();

list.add("mm");
list.add("dd");
classes.students = list;

classesList.add(classes);
}

college.classList = classesList;


colleges = new ArrayList<>();
colleges.add(college);
}
}