教你用两层ExpandableListView嵌套GridView实现三级展示界面

dqwe7108 7年前
   <p>写在前面:</p>    <p>最近项目中使用一个三级展示列表,要求第一级和第二季都可以折叠,并有不同的图标变换,第三层展示数据,可点击。经过一盘折腾,算是实现了,效果就在下面:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/86f504a0f2c804633b8c406721668ab1.gif"></p>    <p>这里写图片描述</p>    <p>思路:</p>    <p>最外层是ExpandableListView,它的子视图又是一个ExpandableListView,这个子ExpandableListView的子视图是我们的第三级展示界面,也就是GridView。分析清楚了之后,写起来就简单了,下面说说遇到的问题。</p>    <p>1,最外层的ExpandableListView嵌套的子ExpandableListView必须解决显示不全的问题。</p>    <p>2,在解决了上面的问题后,会发现,最里层的GridView如果不做处理也会出现显示不全的问题。</p>    <p>3,当上述两个问题都解决了之后,如果我们把最外层和第二层的ExpandableListView都使用自定义的ExpandableListView时,任然会出现子ExpandableListView显示不全问题,所以,这两个ExpandableListView不能使用同一个。</p>    <p>思路和问题都搞定了,我们现在看看主要的类代码:</p>    <p>这是MainActivity.java初始化方法代码</p>    <pre>  <code class="language-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);                      }                  }              }          });      }  }</code></pre>    <p>初始化了ExpandableListView,并设置了每次只展开一个组监听。</p>    <p>ParentExpandAdapter.java代码</p>    <pre>  <code class="language-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          ExpandableListView childExpandLv;      }    }</code></pre>    <p>因为一级只有一个TextView和一个ImageView,比较简单。因为子视图又是一个ExpandableListView,所以这里设置了监听,保证每次只展开一个分组,如果没有这个需求当然可以不设置,另外就是通过判断增加了指示箭头。</p>    <p>二级适配器ChildExpandAdapter.java代码</p>    <pre>  <code class="language-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 {          // 此ExpandableListView的ClildView又是一个GridView          GridView gridView;      }        private List<String> getList() {          List<String> list = new ArrayList<>();          for (int i = 0; i < 50; i++) {              list.add("android " + i);          }          return list;      }  }</code></pre>    <p>根据我们前面的分析,这里的二级ChildView是一个GridView,这里做了初始化,并设置了点击监听。</p>    <p>再来看看最重要的代码——自定义ExpandableListView</p>    <pre>  <code class="language-java">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);      }  }</code></pre>    <p>这里通过测量,计算出子ExpandableListView的高度,解决了显示不全问题,GridView也是一样的。</p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/a778064d1701</p>    <p> </p>