listview嵌套gridview,并实现grid元素部分显示以及点击展开与折叠

时间:2022-09-14 21:38:43

原文链接:http://blog.csdn.net/duguju/article/details/49538341

有时我们需要用GridView显示目录列表,有时甚至是二级的,即listview每一个item里面又各自嵌入一个gridview,但是当二级目录(数据条目)的数量过多时,界面会比较臃肿,这时我们就想要有类似展开与折叠的效果,作者采用的策略是数据分段的分别显示,其中对于显示边界(处于限制显示数目的特定位置)的控件要有数据的动态更新和点击判断操作。效果如图:

listview嵌套gridview,并实现grid元素部分显示以及点击展开与折叠

具体实现:

一、Activity界面

  1. package com.example.gridinlist;
  2. import java.util.Vector;
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.widget.ListView;
  6. public class MainActivity extends Activity {
  7. private ListView listView;
  8. private MyAdapter adapter;
  9. private Vector<String> stringVector = new Vector<String>();
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. initView();
  15. }
  16. private void initView() {
  17. listView = (ListView) findViewById(R.id.list);
  18. adapter = new MyAdapter(this, this.getLayoutInflater(), stringVector);
  19. stringVector.add("0");
  20. stringVector.add("1");
  21. stringVector.add("2");
  22. stringVector.add("3");
  23. stringVector.add("4");
  24. stringVector.add("5");
  25. listView.setAdapter(adapter);
  26. }
  27. }

主Activity,里面只有一个textview(标题)和listview(主体),其中Listview的适配器MyAdapter是自写的(也是实现效果的主要逻辑代码)。

这里我们直传给MyAdapter一个字符串向量,为了简便,不管一级还是二级目录都是用的这一个向量(实际中每个二级子向量应该都是不同的),用户可根据需求自行添加或修改(也可以使用Parcel将其封装为一个二级的数据类型,具体不再赘述)。

Activity布局文件

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context="${relativePackage}.${activityClass}" >
  6. <TextView
  7. android:id="@+id/title"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:gravity="center_horizontal"
  11. android:layout_centerHorizontal="true"
  12. android:text="@string/hello_world" />
  13. <ListView
  14. android:id="@+id/list"
  15. android:layout_width="fill_parent"
  16. android:layout_height="fill_parent"
  17. android:layout_marginLeft="7dip"
  18. android:layout_marginRight="7dip"
  19. android:layout_marginBottom="7dip"
  20. android:layout_below="@+id/title"
  21. android:cacheColorHint="#00000000"
  22. android:drawSelectorOnTop="false"
  23. android:listSelector="#00000000"
  24. android:scrollbars="none"
  25. android:scrollingCache="true"
  26. android:drawingCacheQuality="low"
  27. android:divider="#00000000"
  28. android:dividerHeight="0dip"
  29. android:fadingEdgeLength="0.0sp"
  30. />
  31. </RelativeLayout>

二、自写的istview的Adapter(关键代码)

  1. package com.example.gridinlist;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.Vector;
  5. import android.annotation.SuppressLint;
  6. import android.content.Context;
  7. import android.database.DataSetObserver;
  8. import android.util.Log;
  9. import android.view.LayoutInflater;
  10. import android.view.View;
  11. import android.view.ViewGroup;
  12. import android.widget.AdapterView;
  13. import android.widget.AdapterView.OnItemClickListener;
  14. import android.widget.BaseAdapter;
  15. import android.widget.GridView;
  16. import android.widget.SimpleAdapter;
  17. import android.widget.TextView;
  18. import android.widget.Toast;
  19. public class MyAdapter extends BaseAdapter
  20. {
  21. private static final String TAG = "MyAdapter";
  22. private LayoutInflater inflater;
  23. private Context context;
  24. private Vector<String> vector;
  25. private int numGridShowLimit = 4; //Gridview限定显示数目
  26. /**
  27. * 搜索Adapter初始化
  28. */
  29. public MyAdapter(Context context,LayoutInflater inflater,Vector<String> vector)
  30. {
  31. this.context = context;
  32. this.inflater = inflater;
  33. this.vector = vector;
  34. }
  35. /**
  36. * 初始化View
  37. */
  38. private static class ViewHolder
  39. {
  40. private TextView  titleTextView;
  41. private GridView  contentGridView;
  42. private GridView  contentMoreGridView;
  43. }
  44. /**
  45. * 添加数据
  46. */
  47. @SuppressLint("InflateParams")
  48. @Override
  49. public View getView(int position, View convertView, ViewGroup parent)
  50. {
  51. final ViewHolder viewHolder;
  52. if( convertView == null )
  53. {
  54. convertView = inflater.inflate(R.layout.adapter_listview,null);
  55. viewHolder = new ViewHolder();
  56. viewHolder.titleTextView  = (TextView) convertView.findViewById(R.id.list_txt_title);
  57. viewHolder.contentGridView = (GridView) convertView.findViewById(R.id.list_grid);
  58. viewHolder.contentMoreGridView = (GridView) convertView.findViewById(R.id.list_grid_more);
  59. convertView.setTag(viewHolder);
  60. }
  61. else viewHolder = (ViewHolder) convertView.getTag();
  62. try
  63. {
  64. if(vector != null && vector.size() > 0)
  65. {
  66. final String category = vector.get(position);
  67. if(category != null)
  68. {
  69. viewHolder.titleTextView.setText("list item "+category);
  70. }
  71. if (vector.size() > 0) {
  72. final ArrayList<HashMap<String, Object>> categoryList = new ArrayList<HashMap<String, Object>>();
  73. final ArrayList<HashMap<String, Object>> categorySubList1 = new ArrayList<HashMap<String, Object>>();
  74. final ArrayList<HashMap<String, Object>> categorySubList2 = new ArrayList<HashMap<String, Object>>();
  75. //先封装整个数据向量到categoryList
  76. if (vector != null && vector.size() > 0) {
  77. for (int i = 0; i < vector.size(); i++) {
  78. String o = vector.get(i);
  79. if (o != null) {
  80. HashMap<String, Object> map = new HashMap<String, Object>();
  81. map.put("ItemText", "grid" + o);
  82. categoryList.add(map);
  83. }
  84. }
  85. }
  86. final int mypos = position;
  87. //当数据向量长度大于限定显示的grid数目时,将整个数据向量分成两段
  88. if (vector.size() > numGridShowLimit) {
  89. //封装前段数据到categorySubList1
  90. for (int i = 0; i < numGridShowLimit; i++) {
  91. String o = vector.get(i);
  92. if (o != null) {
  93. if (i==numGridShowLimit-1) {
  94. HashMap<String, Object> map = new HashMap<String, Object>();
  95. if (viewHolder.contentMoreGridView.getVisibility()==View.GONE) {
  96. //若处于折叠状态则将限定数目的位置的数据修改为“+”(用于点击展开)
  97. map.put("ItemText", "" + "+");
  98. }else {
  99. //若处于展开状态则限定数目的位置的数据正常显示
  100. map.put("ItemText", "grid" + o);
  101. }
  102. categorySubList1.add(map);
  103. }else {
  104. HashMap<String, Object> map = new HashMap<String, Object>();
  105. map.put("ItemText", "grid" + o);
  106. categorySubList1.add(map);
  107. }
  108. }
  109. }
  110. //封装后段数据到categorySubList2
  111. for (int i = numGridShowLimit; i < vector.size(); i++) {
  112. String o = vector.get(i);
  113. if (o != null) {
  114. HashMap<String, Object> map = new HashMap<String, Object>();
  115. map.put("ItemText", "grid" + o);
  116. categorySubList2.add(map);
  117. }
  118. }
  119. HashMap<String, Object> map = new HashMap<String, Object>();
  120. map.put("ItemText", "-"); //在第二段的最后添加一个“-”数据(用于点击折叠)
  121. categorySubList2.add(map);
  122. //创建第一部分GridView的adapter
  123. final SimpleAdapter simpleAdapter1 = new SimpleAdapter(context, categorySubList1,
  124. R.layout.adapter_gridview,
  125. new String[] { "ItemText" }, // 对应map的Key
  126. new int[] { R.id.ItemText }); // 对应R的Id
  127. viewHolder.contentGridView.setAdapter(simpleAdapter1);
  128. //创建第二部分GridView的adapter
  129. final SimpleAdapter simpleAdapter2 = new SimpleAdapter(context, categorySubList2,
  130. R.layout.adapter_gridview,
  131. new String[] { "ItemText" }, // 对应map的Key
  132. new int[] { R.id.ItemText }); // 对应R的Id
  133. viewHolder.contentMoreGridView.setAdapter(simpleAdapter2);
  134. //设置第二部分GridView的adapter中的具体item点击事件
  135. viewHolder.contentMoreGridView.setOnItemClickListener(new OnItemClickListener() {
  136. public void onItemClick(AdapterView<?> AdapterView, View view,int pos, long row) {
  137. if (categoryList.size()>numGridShowLimit && pos==categoryList.size()-numGridShowLimit) {
  138. //若点击末尾的“-”,则将gridview折叠,并修改第一部分最后位置为“+”(可展开状态)
  139. View rel =  (View) viewHolder.contentGridView.getChildAt(numGridShowLimit-1);
  140. TextView tv =  (TextView) rel.findViewById(R.id.ItemText);
  141. tv.setText("+");
  142. viewHolder.contentMoreGridView.setVisibility(View.GONE);
  143. }else {
  144. view.setTag(mypos*100+numGridShowLimit+pos);
  145. Toast.makeText(context, " list position:"+ mypos+"\ngrid position:"+pos, Toast.LENGTH_SHORT).show();
  146. }
  147. }
  148. });
  149. }
  150. else {
  151. //若数据向量数目不大于限定的显示数目,则正常创建第一部分GridView的adapter(直接使用整体数据categoryList)
  152. final SimpleAdapter simpleAdapter = new SimpleAdapter(context, categoryList,
  153. R.layout.adapter_gridview,
  154. new String[] { "ItemText" }, // 对应map的Key
  155. new int[] { R.id.ItemText }); // 对应R的Id
  156. viewHolder.contentGridView.setAdapter(simpleAdapter);
  157. }
  158. //设置第一部分GridView的adapter中的具体item点击事件
  159. viewHolder.contentGridView.setOnItemClickListener(new OnItemClickListener() {
  160. public void onItemClick(AdapterView<?> AdapterView, View view,int pos, long row) {
  161. if (categoryList.size()>numGridShowLimit && pos==numGridShowLimit-1) {
  162. TextView tv =  (TextView) view.findViewById(R.id.ItemText);
  163. String content = tv.getText().toString();
  164. if (content.equals("+")) {
  165. //若点击“+”,则进行展开操作,即显示第二部分gridview,并修改最后位置为“+”
  166. tv.setText("grid"+vector.get(numGridShowLimit-1));
  167. viewHolder.contentMoreGridView.setVisibility(View.VISIBLE);
  168. }else {
  169. view.setTag(mypos*100+pos);
  170. Toast.makeText(context, " list position:"+ mypos+"\ngrid position:"+pos, Toast.LENGTH_SHORT).show();
  171. }
  172. }else {
  173. view.setTag(mypos*100+pos);
  174. Toast.makeText(context, " list position:"+ mypos+"\ngrid position:"+pos, Toast.LENGTH_SHORT).show();
  175. }
  176. }
  177. });
  178. }
  179. }
  180. }
  181. catch (Exception e)
  182. {
  183. e.printStackTrace();
  184. Log.e(TAG, "Exception");
  185. }
  186. return convertView;
  187. }
  188. @Override
  189. public int getCount()
  190. {
  191. return vector.size();
  192. }
  193. @Override
  194. public Object getItem(int position) {
  195. return null;
  196. }
  197. @Override
  198. public long getItemId(int position) {
  199. return 0;
  200. }
  201. @Override
  202. public void unregisterDataSetObserver(DataSetObserver observer)
  203. {
  204. if (observer != null) {
  205. super.unregisterDataSetObserver(observer);
  206. }
  207. }
  208. }

具体步骤请看代码中的注释,需要注意的是,里面的GridView使用的是自写的控件,因为若使用Android自带的GridView,会出现在ListView中只显示一行grid的情况,这是因为ListView无法动态获取GridView的数目而无法确定它的高度,因此默认认为只有一行数据。

解决方法是:在自写的GridView里面,需要重写onMeasure方法,这样就可以得到GridView的高度了,代码如下:

  1. package com.example.gridinlist;
  2. import android.widget.GridView;
  3. public class MyGridView extends GridView
  4. {
  5. public MyGridView(android.content.Context context,
  6. android.util.AttributeSet attrs)
  7. {
  8. super(context, attrs);
  9. }
  10. /**
  11. * 重写的onMeasure方法
  12. */
  13. public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  14. {
  15. int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
  16. MeasureSpec.AT_MOST);
  17. super.onMeasure(widthMeasureSpec, expandSpec);
  18. }
  19. }

ListView的item布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="fill_parent"
  5. android:layout_height="wrap_content"
  6. android:layout_marginTop="1dip"
  7. android:layout_marginBottom="1dip"
  8. android:orientation="vertical"
  9. android:baselineAligned="false"
  10. android:background="#ffffff"
  11. >
  12. <RelativeLayout
  13. android:id="@+id/list_rel"
  14. android:layout_width="fill_parent"
  15. android:layout_height="wrap_content"
  16. android:layout_marginTop="10dip"
  17. android:layout_marginBottom="10dip"
  18. >
  19. <ImageView
  20. android:id="@+id/list_img_icon"
  21. android:layout_width="3dip"
  22. android:layout_height="17dip"
  23. android:layout_marginLeft="15dip"
  24. android:contentDescription="@null"
  25. android:scaleType="fitXY"
  26. android:layout_centerVertical="true"
  27. android:src="@drawable/selected_orange"
  28. android:visibility="visible" />
  29. <TextView
  30. android:id="@+id/list_txt_title"
  31. android:layout_width="wrap_content"
  32. android:layout_height="wrap_content"
  33. android:layout_toRightOf="@+id/list_img_icon"
  34. android:layout_marginLeft="7dip"
  35. android:layout_marginRight="7dip"
  36. android:gravity="center"
  37. android:layout_centerVertical="true"
  38. android:singleLine="true"
  39. />
  40. </RelativeLayout>
  41. <com.example.gridinlist.MyGridView
  42. android:id="@+id/list_grid"
  43. android:layout_width="fill_parent"
  44. android:layout_height="fill_parent"
  45. android:layout_marginBottom="1dip"
  46. android:columnWidth="70dip"
  47. android:horizontalSpacing="10dip"
  48. android:verticalSpacing="10dip"
  49. android:listSelector="@android:color/transparent"
  50. android:numColumns="4"
  51. android:paddingLeft="15dip"
  52. android:paddingRight="15dip"
  53. android:scrollbars="none"
  54. android:stretchMode="columnWidth"
  55. android:visibility="visible" >
  56. </com.example.gridinlist.MyGridView>
  57. <com.example.gridinlist.MyGridView
  58. android:id="@+id/list_grid_more"
  59. android:layout_width="fill_parent"
  60. android:layout_height="fill_parent"
  61. android:layout_marginTop="10dip"
  62. android:layout_marginBottom="1dip"
  63. android:columnWidth="70dip"
  64. android:horizontalSpacing="10dip"
  65. android:verticalSpacing="10dip"
  66. android:listSelector="@android:color/transparent"
  67. android:numColumns="4"
  68. android:paddingLeft="15dip"
  69. android:paddingRight="15dip"
  70. android:scrollbars="none"
  71. android:stretchMode="columnWidth"
  72. android:visibility="gone" >
  73. </com.example.gridinlist.MyGridView>
  74. </LinearLayout>

里面包含一个标题,以及两个自写的GridView(一个显示前面部分,另一个显示剩下的,点击展开与折叠其实就是第二个GridView的显示与隐藏)

GridView的item布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <TextView
  6. android:id="@+id/ItemText"
  7. android:layout_width="70dip"
  8. android:layout_height="32dip"
  9. android:background="@drawable/btn_txt_bg"
  10. android:text=""
  11. android:gravity="center"
  12. />
  13. </RelativeLayout>

只是简单的一个TextView,用户想扩展或丰富可自行修改。

代码下载连接:http://download.csdn.net/detail/duguju/9233759

listview嵌套gridview,并实现grid元素部分显示以及点击展开与折叠的更多相关文章

  1. ListView嵌套GridView显示不完整的解决方案

    转载注明出处:http://blog.csdn.net/allen315410/article/details/40152987 近期在做项目中,有个模块须要在ListView中嵌套一个GridVie ...

  2. Flutter中用ListView嵌套GridView报错异常

    flutter中的ListView组件和GridView组件都是常用的布局组件,有时候ListView中需要嵌套GridView来使用,例如下图: 这种情况就需要在ListView里面再嵌套一个Gri ...

  3. android listView嵌套gridview的使用心得

    在开发的过程中可能需要用到listview嵌套gridview的场景,但是在Android中, 不能在一个拥有Scrollbar的组件中嵌入另一个拥有Scrollbar的组件,因为这不科学,会混淆滑动 ...

  4. ScrollView嵌套ListView嵌套GridView的上下拉以及加载更多

    ScrollView 效果 ScrollView 说明 一个ScrollView 嵌套ListView 嵌套GridView的上拉加载更多,下拉刷新的demo. 主要是重写了GridView和Lsit ...

  5. ListView嵌套GridView

    首先,我们通过两个实例来了解下本篇文章所讲的重点,看下图: 微博: 陌陌: 大家应该对这两款软件并不陌生,接下来,我将列举下本文将要实现的几个点: 1.ListView嵌套GridView,互不冲突, ...

  6. ListView嵌套GridView,显示不全解决办法

    ListView嵌套GridView时,遇到了GridView只显示一行,其余都显示不出来的问题,最终解决办法如下: 需要自定义GridView,重新绘制高度即可: public class MyGr ...

  7. ListView嵌套GridView使用详解及注意事项

    ListView嵌套GridView即ListView的每个Item中都包含一个GridView:需要注意的是由于ListView和GridView都是可滑动的控件. 所以需要自定义GridView, ...

  8. 【Android】listview 嵌套gridview报错,代码&colon;”during second layout pass&colon; posting in next frame

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 公众号:程序员小冰 说明:本人曾经在listview嵌套gridview出现 ...

  9. Android中ListView嵌套GridView的简单消息流UI&lpar;解决宽高问题&rpar;

    最近搞一个项目,需要用到类似于新浪微博的消息流,即每一项有文字.有九宫格图片,因此这就涉及到ListView或者ScrollView嵌套GridView的问题.其中GridView的高度问题在网上都很 ...

随机推荐

  1. Jtable 表格按多列排序(支持中文汉字排序)

    这两天公司让做一个Jtable表格的排序,首先按A列排序,在A列相等时按B列排序,B列相等时按C列排序,ABC三列可以任意指定,最多分三列,这样的一个需求.由于我是大神,所以必须做了出来.ok,不自恋 ...

  2. 在MySQL中,如何计算一组数据的中位数?

    要得到一组数据的中位数(例如某个地区或某家公司的收入中位数),我们首先要将这一任务细分为3个小任务: 将数据排序,并给每一行数据给出其在所有数据中的排名. 找出中位数的排名数字. 找出中间排名对应的值 ...

  3. Java中的流

    一.Java中流的原理 流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以“流”的方式进行.设备可以是文件,网络,内存等. 四种基本流InputStream,Ou ...

  4. mui H5 js动态添加不同类型的数据

    html页面需要添加的页面的数据格式 <ul class="mui-table-view" id="OA_task_1"> <li class ...

  5. 动软代码生成器三层用于winform

    DBUtility项目中的DbHelperSQL.cs (找自己对应的数据库类型) 修改前20行中的数据库连接字符串获取方式为: //数据库连接字符串(web.config来配置),多数据库可使用Db ...

  6. zookeeper基本原理及适用场景 转:http&colon;&sol;&sol;blog&period;chinaunix&period;net&sol;uid-26748613-id-4536290&period;html

    1.1 zookeeper简介 Zookeeper 是 Hadoop 生态系统中的协同实现,是Hadoop集群管理的一个必不可少的模块,它主要来控制集群中的数据,如它管理Hadoop集群中的NameN ...

  7. node项目运行报错

    Cannot find module 'webpack/bin/config-optimist' 在项目里面运行npm i webpack-dev-server Cannot find module ...

  8. 爬虫之requests请求库高级应用

    1.SSL Cert Verification #证书验证(大部分网站都是https) import requests respone=requests.get('https://www.12306. ...

  9. Oracle的一些经典SQL面试题

    实例1:测试数据: create table nba( team   varchar2(20), year number(4) ) SQL> select * from nba; TEAM    ...

  10. &lbrack;development&rsqb;&lbrack;lockless&rsqb;&lbrack;dpdk&rsqb; 无锁队列

    dpdk: http://dpdk.org/doc/guides/prog_guide/ring_lib.html#ring-library linux: https://lwn.net/Articl ...