参考资料
https://blog.youkuaiyun.com/yaya_soft/article/details/25796453
https://blog.youkuaiyun.com/benweizhu/article/details/6871244
前言
现在android开发经常把使用ListView改为使用RecyclerView,实话实说,RecyclerView确实非常好用。但在某些情况下我还是倾向于使用ListView。但这次我不是用ListView,而是它的子类ExpandableListView。如图,我需要实现两个ListView的嵌套。
能看懂?那好,接下来代码实现
视图
main.xml
<ExpandableListView
android:layout_below="@id/source_company_number_text"
android:id="@+id/source_company_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ExpandableListView>
<TextView
android:id="@+id/source_more"
android:layout_below="@+id/source_company_list"
android:textColor="@color/blue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查看更多"
android:layout_centerHorizontal="true"
/>
group_date.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/gruop_date"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_38_y"
android:text="2018.1.1"
/>
</LinearLayout>
child_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<TextView
android:layout_marginLeft="@dimen/dp_50_x"
android:id="@+id/child_time"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_34_y"
android:text="12:00"
android:gravity="center"
/>
<TextView
android:id="@+id/child_detail"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_34_y"
android:text="杀青"
android:gravity="center"
android:layout_marginLeft="@dimen/dp_12_x"
/>
</LinearLayout>
这点代码还是非常简单的,完全具备暴力美学
java代码
Activtiy.java
@BindView(R.id.source_company_list)
ExpandableListView company_list;
@BindView(R.id.source_more)
TextView company_more;
Public void showResult(Company company){
companyListAdapter = new CompanyListAdapter(this,sourceDataBean);
company_list.setAdapter(companyListAdapter);
params = ListViewParamsUtils.setListViewHeightBasedOnChildren(company_list);
for (int i = 0; i < sourceDataBean.getProcessing_company().getDate_lists().size(); i++) {
company_list.expandGroup(i);
}
company_list.setGroupIndicator(null);//取消箭头//设置父节点(章目录)不可点击
//设置展开不关闭
company_list.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
return true;//返回true,表示不可点击
}
});
params.height = params.height/4;//只显示1/4,当点击更多时显示全部
company_list.setLayoutParams(params);
company_more.setOnClickListener(this);
}
东西太多?别急,我们慢慢来梳理一下。
首先,传入的参数company到底有什么?
分析这里面的结构,我创建了一个Company类
Company.java
@Data
public class Company {
private List<Dates> date_list = new ArrayList<>();
@Data
public static class Dates{
private String date;
private List<Times> time_list = new ArrayList<>();
@Data
public static class Times{
private String time;
private String detail;
}
}
}
所以之前传进来的company就是网络请求后获取到的数据
接下来就是适配器的设计了
CompanyListAdapter.java
public class CompanyListAdapter extends BaseExpandableListAdapter {
// private int mExpandedLayout;
private int groupLayout;
private int[] groups;
private int childLayout;
private int[] childs;
private Company sourceDataBean;
private String[] date;
private data[] datas;
private LayoutInflater mInflater;
private Map<String,data[]> map = new HashMap<>();
public void setReuslt(){
date = new String[sourceDataBean.getDate_list().size()];
for (int i=0;i<sourceDataBean.getDate_list().size();i++){
date[i] = sourceDataBean.getDate_list().get(i).getDate();
datas = new data[sourceDataBean.getDate_list().get(i).getTime_list().size()];
for (int j = 0;j<sourceDataBean.getDate_list().get(i).getTime_list().size();j++){
datas[j] = new data(sourceDataBean.getDate_list().get(i).getTime_list().get(j).getTime(),sourceDataBean.getDate_list().get(i).getTime_list().get(j).getDetail());
}
map.put(date[i],datas);
}
}
public CompanyListAdapter(Context context, Company sourceDataBean){
this.sourceDataBean =sourceDataBean;
groupLayout = R.layout.group_date;
groups = new int[]{R.id.gruop_date};
childLayout = R.layout.child_detail;
childs = new int[]{R.id.child_time,R.id.child_detail};
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setReuslt();
}
@Override
public int getGroupCount() {
return date.length;
}
@Override
public int getChildrenCount(int i) {
return map.get(date[i]).length;
}
@Override
public Object getGroup(int i) {
return date[i];
}
@Override
public Object getChild(int i, int i1) {
return map.get(date[i])[i1];
}
@Override
public long getGroupId(int i) {
return i;
}
@Override
public long getChildId(int i, int i1) {
return i1;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
View v;
if (view==null){
v= newGroupView(b,viewGroup);
}else {
v = view;
}
bindGroupView(v,date,i);
return v;
}
private void bindGroupView(View v, String[] date,int i) {
int len = date.length;
TextView textView = v.findViewById(R.id.gruop_date);
textView.setText(date[i]);
}
private View newGroupView(boolean b, ViewGroup viewGroup) {
return mInflater.inflate(groupLayout,viewGroup,false);
}
@Override
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
View v;
if (view == null){
v= newChildView(b,viewGroup);
}else {
v = view;
}
bindChildView(v,map.get(date[i])[i1]);
return v;
}
private void bindChildView(View v, data data) {
TextView textView = v.findViewById(R.id.child_time);
TextView textView1 = v.findViewById(R.id.child_detail);
textView.setText(data.getTime());
textView1.setText(data.getAction());
}
private View newChildView(boolean b, ViewGroup viewGroup) {
return mInflater.inflate(childLayout,viewGroup,false);
}
/**
* 指定子视图是否可选择
* @param i
* @param i1
* @return
*/
@Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
@Data
class data{
private String time;
private String action;
public data(String time ,String action){
this.time = time;
this.action = action;
}
}
}
代码有点长了,这里解释一下,设计思路是
- 将数据传进来适配器
- getGroupView 方法中返回group_date视图,并写入相应数据
- getChildVierw 方法中返回child_detail视图,并写入相应数据
- 这里代码看起来虽然多,但关键只需要理解newGroupView和BindGroupView方法里面的代码
这里就完成了基本的代码完成了
出现的一些问题
显示只显示一行或者完全不显示,这里可以通过去测量它本身的大小去自定义显示容器的大小
建立工具类
ListViewParamsUtils.java
public static ViewGroup.LayoutParams setListViewHeightBasedOnChildren(ExpandableListView listView){
ExpandableListAdapter listAdapter = listView.getExpandableListAdapter();
if (listAdapter == null) {
return null;
}
//初始化高度
int totalHeight = 0;
//分割线数量
int count = 0;
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View listItem = listAdapter.getGroupView(i,true,null,listView);
//计算子项View的宽高,注意listview所在的要是linearlayout布局
listItem.measure(0, 0);
//统计所有子项的总高度
totalHeight += listItem.getMeasuredHeight();
count++;
for (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
View childItem = listAdapter.getChildView(i,j,true,null,listView);
childItem.measure(0,0);
totalHeight += childItem.getMeasuredHeight();
count++;
}
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
/*
* listView.getDividerHeight()获取子项间分隔符占用的高度,有多少项就乘以多少个减一
* params.height最后得到整个ListView完整显示需要的高度
* 最后将params.height设置为listview的高度
*/
params.height = totalHeight + (listView.getDividerHeight() * (count - 1));
return params;
}
然后在activity调用方法
ViewGroup.LayoutParams params = ListViewParamsUtils.setListViewHeightBasedOnChildren(company_list);
company_list.setLayoutParams(params);
扩展小功能
有时候获取的数据过多,并不想让它占的视图过大。我们可以通过获取到的params设置大小,当想看全部信息时展开,如下图
监听实现方法
private void showCompanyAll() {
if (companyAll){
params.height = params.height/4;//只显示1/4,当点击更多时显示全部
company_list.setLayoutParams(params);
companyAll = false;
company_more.setText("查看更多");
}else {
params.height = params.height*4;//显示全部,当点击更多时显示全部
company_list.setLayoutParams(params);
companyAll = true;
company_more.setText("收回");
}
}
有趣的东西太多,人生太短,抓紧时间,努力学习