最近项目中使用一个三级展示列表,要求第一级和第二季都可以折叠,并有不同的图标变换,第三层展示数据,可点击。经过一盘折腾,算是实现了,效果就在下面:
思路:
最外层是ExpandableListView,它的子视图又是一个ExpandableListView,这个子ExpandableListView的子视图是我们的第三级展示界面,也就是GridView。分析清楚了之后,写起来就简单了,下面说说遇到的问题。
1,最外层的ExpandableListView嵌套的子ExpandableListView必须解决显示不全的问题。
2,在解决了上面的问题后,会发现,最里层的GridView如果不做处理也会出现显示不全的问题。
3,当上述两个问题都解决了之后,如果我们把最外层和第二层的ExpandableListView都使用自定义的ExpandableListView时,任然会出现子ExpandableListView显示不全问题,所以,这两个ExpandableListView不能使用同一个。
思路和问题都搞定了,我们现在看看主要的类代码:
这是MainActivity.Java初始化方法代码
public class MainActivity extends AppCompatActivity { private ExpandableListView expandableListView; private List<String> groupList = new ArrayList<>(); private ParentExpandAdapter parentExpandAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initData(); initView(); } private void initData() { for (int i = 0; i < 11; i++) { groupList.add("Android工程师之版权 " + (1 + i)); } } private void initView() { setContentView(R.layout.activity_main); expandableListView = (ExpandableListView) findViewById(R.id.expand_main); parentExpandAdapter = new ParentExpandAdapter(MainActivity.this, groupList); expandableListView.setAdapter(parentExpandAdapter); expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { for (int i = 0; i < parentExpandAdapter.getGroupCount(); i++) { if (i != groupPosition) { expandableListView.collapseGroup(i); } } } }); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
初始化了ExpandableListView,并设置了每次只展开一个组监听。
ParentExpandAdapter.java代码
public class ParentExpandAdapter extends BaseExpandableListAdapter { private Context context; private List<String> parentList; public ParentExpandAdapter(Context context, List<String> parentList) { this.context = context; this.parentList = parentList; } @Override public int getGroupCount() { return parentList.size(); } @Override public int getChildrenCount(int groupPosition) { return 5; } @Override public Object getGroup(int groupPosition) { return parentList.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return parentList.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) { ParentViewHolder parentHolder; if (null == convertView) { parentHolder = new ParentViewHolder(); convertView = View.inflate(context, R.layout.fire_tab_parent_group_item, null); parentHolder.parentTv = (TextView) convertView.findViewById(R.id.parentGroupTV); parentHolder.parentIv = (ImageView) convertView.findViewById(R.id.iv_parent_group_indicator); convertView.setTag(parentHolder); } else { parentHolder = (ParentViewHolder) convertView.getTag(); } parentHolder.parentTv.setText(parentList.get(groupPosition)); if (isExpanded) { parentHolder.parentIv.setImageResource(R.drawable.icon_arrow_up); } else { parentHolder.parentIv.setImageResource(R.drawable.icon_arrow_down); } return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ChildViewHolder childHolder; if (null == convertView) { childHolder = new ChildViewHolder(); convertView = View.inflate(context, R.layout.item_expand_group_child, null); childHolder.childExpandLv = (ExpandableListView) convertView.findViewById(R.id.expand_group_item); convertView.setTag(childHolder); } else { childHolder = (ChildViewHolder) convertView.getTag(); } childHolder.childExpandLv.setAdapter(new ChildExpandAdapter(context, parentList.subList(3, 7))); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } class ParentViewHolder { TextView parentTv; ImageView parentIv; } class ChildViewHolder { ExpandableListView childExpandLv; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
因为一级只有一个TextView和一个ImageView,比较简单。因为子视图又是一个ExpandableListView,所以这里设置了监听,保证每次只展开一个分组,如果没有这个需求当然可以不设置,另外就是通过判断增加了指示箭头。
二级适配器ChildExpandAdapter.java代码
public class ChildExpandAdapter extends BaseExpandableListAdapter { private Context context; private List<String> parentList; public ChildExpandAdapter(Context context, List<String> parentList) { this.context = context; this.parentList = parentList; } @Override public int getGroupCount() { return parentList.size(); } @Override public int getChildrenCount(int groupPosition) { return 1; } @Override public Object getGroup(int groupPosition) { return parentList.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return parentList.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) { ParentViewHolder parentHolder; if (null == convertView) { parentHolder = new ParentViewHolder(); convertView = View.inflate(context, R.layout.fire_tab_child_group_item, null); parentHolder.parentTv = (TextView) convertView.findViewById(R.id.childGroupTV); parentHolder.parentIv = (ImageView) convertView.findViewById(R.id.iv_fire_tab_child_indicator); convertView.setTag(parentHolder); } else { parentHolder = (ParentViewHolder) convertView.getTag(); } parentHolder.parentTv.setText(parentList.get(groupPosition)); if (isExpanded) { parentHolder.parentIv.setImageResource(R.drawable.icon_arrow_up); } else { parentHolder.parentIv.setImageResource(R.drawable.icon_arrow_down); } return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ChildViewHolder childHolder; if (null == convertView) { childHolder = new ChildViewHolder(); convertView = View.inflate(context, R.layout.item_child_child, null); childHolder.gridView = (GridView) convertView.findViewById(R.id.gv_child_child_item); convertView.setTag(childHolder); } else { childHolder = (ChildViewHolder) convertView.getTag(); } childHolder.gridView.setAdapter(new GridViewAdapter(context, getList())); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } class ParentViewHolder { TextView parentTv; ImageView parentIv; } class ChildViewHolder { GridView gridView; } private List<String> getList() { List<String> list = new ArrayList<>(); for (int i = 0; i < 50; i++) { list.add("android " + i); } return list; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
根据我们前面的分析,这里的二级ChildView是一个GridView,这里做了初始化,并设置了点击监听。
再来看看最重要的代码——自定义ExpandableListView
public class CustomExpandableListview extends ExpandableListView { public CustomExpandableListview(Context context) { super(context); } public CustomExpandableListview(Context context, AttributeSet attrs) { super(context, attrs); } public CustomExpandableListview(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
这里通过测量,计算出子ExpandableListView的高度,解决了显示不全问题,GridView也是一样的。