原文链接:http://blog.csdn.net/duguju/article/details/49538341
有时我们需要用GridView显示目录列表,有时甚至是二级的,即listview每一个item里面又各自嵌入一个gridview,但是当二级目录(数据条目)的数量过多时,界面会比较臃肿,这时我们就想要有类似展开与折叠的效果,作者采用的策略是数据分段的分别显示,其中对于显示边界(处于限制显示数目的特定位置)的控件要有数据的动态更新和点击判断操作。效果如图:
具体实现:
一、Activity界面
- package com.example.gridinlist;
- import java.util.Vector;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.ListView;
- public class MainActivity extends Activity {
- private ListView listView;
- private MyAdapter adapter;
- private Vector<String> stringVector = new Vector<String>();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- }
- private void initView() {
- listView = (ListView) findViewById(R.id.list);
- adapter = new MyAdapter(this, this.getLayoutInflater(), stringVector);
- stringVector.add("0");
- stringVector.add("1");
- stringVector.add("2");
- stringVector.add("3");
- stringVector.add("4");
- stringVector.add("5");
- listView.setAdapter(adapter);
- }
- }
主Activity,里面只有一个textview(标题)和listview(主体),其中Listview的适配器MyAdapter是自写的(也是实现效果的主要逻辑代码)。
这里我们直传给MyAdapter一个字符串向量,为了简便,不管一级还是二级目录都是用的这一个向量(实际中每个二级子向量应该都是不同的),用户可根据需求自行添加或修改(也可以使用Parcel将其封装为一个二级的数据类型,具体不再赘述)。
Activity布局文件
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="${relativePackage}.${activityClass}" >
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:text="@string/hello_world" />
- <ListView
- android:id="@+id/list"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_marginLeft="7dip"
- android:layout_marginRight="7dip"
- android:layout_marginBottom="7dip"
- android:layout_below="@+id/title"
- android:cacheColorHint="#00000000"
- android:drawSelectorOnTop="false"
- android:listSelector="#00000000"
- android:scrollbars="none"
- android:scrollingCache="true"
- android:drawingCacheQuality="low"
- android:divider="#00000000"
- android:dividerHeight="0dip"
- android:fadingEdgeLength="0.0sp"
- />
- </RelativeLayout>
二、自写的istview的Adapter(关键代码)
- package com.example.gridinlist;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Vector;
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.database.DataSetObserver;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.BaseAdapter;
- import android.widget.GridView;
- import android.widget.SimpleAdapter;
- import android.widget.TextView;
- import android.widget.Toast;
- public class MyAdapter extends BaseAdapter
- {
- private static final String TAG = "MyAdapter";
- private LayoutInflater inflater;
- private Context context;
- private Vector<String> vector;
- private int numGridShowLimit = 4; //Gridview限定显示数目
- /**
- * 搜索Adapter初始化
- */
- public MyAdapter(Context context,LayoutInflater inflater,Vector<String> vector)
- {
- this.context = context;
- this.inflater = inflater;
- this.vector = vector;
- }
- /**
- * 初始化View
- */
- private static class ViewHolder
- {
- private TextView titleTextView;
- private GridView contentGridView;
- private GridView contentMoreGridView;
- }
- /**
- * 添加数据
- */
- @SuppressLint("InflateParams")
- @Override
- public View getView(int position, View convertView, ViewGroup parent)
- {
- final ViewHolder viewHolder;
- if( convertView == null )
- {
- convertView = inflater.inflate(R.layout.adapter_listview,null);
- viewHolder = new ViewHolder();
- viewHolder.titleTextView = (TextView) convertView.findViewById(R.id.list_txt_title);
- viewHolder.contentGridView = (GridView) convertView.findViewById(R.id.list_grid);
- viewHolder.contentMoreGridView = (GridView) convertView.findViewById(R.id.list_grid_more);
- convertView.setTag(viewHolder);
- }
- else viewHolder = (ViewHolder) convertView.getTag();
- try
- {
- if(vector != null && vector.size() > 0)
- {
- final String category = vector.get(position);
- if(category != null)
- {
- viewHolder.titleTextView.setText("list item "+category);
- }
- if (vector.size() > 0) {
- final ArrayList<HashMap<String, Object>> categoryList = new ArrayList<HashMap<String, Object>>();
- final ArrayList<HashMap<String, Object>> categorySubList1 = new ArrayList<HashMap<String, Object>>();
- final ArrayList<HashMap<String, Object>> categorySubList2 = new ArrayList<HashMap<String, Object>>();
- //先封装整个数据向量到categoryList
- if (vector != null && vector.size() > 0) {
- for (int i = 0; i < vector.size(); i++) {
- String o = vector.get(i);
- if (o != null) {
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("ItemText", "grid" + o);
- categoryList.add(map);
- }
- }
- }
- final int mypos = position;
- //当数据向量长度大于限定显示的grid数目时,将整个数据向量分成两段
- if (vector.size() > numGridShowLimit) {
- //封装前段数据到categorySubList1
- for (int i = 0; i < numGridShowLimit; i++) {
- String o = vector.get(i);
- if (o != null) {
- if (i==numGridShowLimit-1) {
- HashMap<String, Object> map = new HashMap<String, Object>();
- if (viewHolder.contentMoreGridView.getVisibility()==View.GONE) {
- //若处于折叠状态则将限定数目的位置的数据修改为“+”(用于点击展开)
- map.put("ItemText", "" + "+");
- }else {
- //若处于展开状态则限定数目的位置的数据正常显示
- map.put("ItemText", "grid" + o);
- }
- categorySubList1.add(map);
- }else {
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("ItemText", "grid" + o);
- categorySubList1.add(map);
- }
- }
- }
- //封装后段数据到categorySubList2
- for (int i = numGridShowLimit; i < vector.size(); i++) {
- String o = vector.get(i);
- if (o != null) {
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("ItemText", "grid" + o);
- categorySubList2.add(map);
- }
- }
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("ItemText", "-"); //在第二段的最后添加一个“-”数据(用于点击折叠)
- categorySubList2.add(map);
- //创建第一部分GridView的adapter
- final SimpleAdapter simpleAdapter1 = new SimpleAdapter(context, categorySubList1,
- R.layout.adapter_gridview,
- new String[] { "ItemText" }, // 对应map的Key
- new int[] { R.id.ItemText }); // 对应R的Id
- viewHolder.contentGridView.setAdapter(simpleAdapter1);
- //创建第二部分GridView的adapter
- final SimpleAdapter simpleAdapter2 = new SimpleAdapter(context, categorySubList2,
- R.layout.adapter_gridview,
- new String[] { "ItemText" }, // 对应map的Key
- new int[] { R.id.ItemText }); // 对应R的Id
- viewHolder.contentMoreGridView.setAdapter(simpleAdapter2);
- //设置第二部分GridView的adapter中的具体item点击事件
- viewHolder.contentMoreGridView.setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView<?> AdapterView, View view,int pos, long row) {
- if (categoryList.size()>numGridShowLimit && pos==categoryList.size()-numGridShowLimit) {
- //若点击末尾的“-”,则将gridview折叠,并修改第一部分最后位置为“+”(可展开状态)
- View rel = (View) viewHolder.contentGridView.getChildAt(numGridShowLimit-1);
- TextView tv = (TextView) rel.findViewById(R.id.ItemText);
- tv.setText("+");
- viewHolder.contentMoreGridView.setVisibility(View.GONE);
- }else {
- view.setTag(mypos*100+numGridShowLimit+pos);
- Toast.makeText(context, " list position:"+ mypos+"\ngrid position:"+pos, Toast.LENGTH_SHORT).show();
- }
- }
- });
- }
- else {
- //若数据向量数目不大于限定的显示数目,则正常创建第一部分GridView的adapter(直接使用整体数据categoryList)
- final SimpleAdapter simpleAdapter = new SimpleAdapter(context, categoryList,
- R.layout.adapter_gridview,
- new String[] { "ItemText" }, // 对应map的Key
- new int[] { R.id.ItemText }); // 对应R的Id
- viewHolder.contentGridView.setAdapter(simpleAdapter);
- }
- //设置第一部分GridView的adapter中的具体item点击事件
- viewHolder.contentGridView.setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView<?> AdapterView, View view,int pos, long row) {
- if (categoryList.size()>numGridShowLimit && pos==numGridShowLimit-1) {
- TextView tv = (TextView) view.findViewById(R.id.ItemText);
- String content = tv.getText().toString();
- if (content.equals("+")) {
- //若点击“+”,则进行展开操作,即显示第二部分gridview,并修改最后位置为“+”
- tv.setText("grid"+vector.get(numGridShowLimit-1));
- viewHolder.contentMoreGridView.setVisibility(View.VISIBLE);
- }else {
- view.setTag(mypos*100+pos);
- Toast.makeText(context, " list position:"+ mypos+"\ngrid position:"+pos, Toast.LENGTH_SHORT).show();
- }
- }else {
- view.setTag(mypos*100+pos);
- Toast.makeText(context, " list position:"+ mypos+"\ngrid position:"+pos, Toast.LENGTH_SHORT).show();
- }
- }
- });
- }
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- Log.e(TAG, "Exception");
- }
- return convertView;
- }
- @Override
- public int getCount()
- {
- return vector.size();
- }
- @Override
- public Object getItem(int position) {
- return null;
- }
- @Override
- public long getItemId(int position) {
- return 0;
- }
- @Override
- public void unregisterDataSetObserver(DataSetObserver observer)
- {
- if (observer != null) {
- super.unregisterDataSetObserver(observer);
- }
- }
- }
具体步骤请看代码中的注释,需要注意的是,里面的GridView使用的是自写的控件,因为若使用Android自带的GridView,会出现在ListView中只显示一行grid的情况,这是因为ListView无法动态获取GridView的数目而无法确定它的高度,因此默认认为只有一行数据。
解决方法是:在自写的GridView里面,需要重写onMeasure方法,这样就可以得到GridView的高度了,代码如下:
- package com.example.gridinlist;
- import android.widget.GridView;
- public class MyGridView extends GridView
- {
- public MyGridView(android.content.Context context,
- android.util.AttributeSet attrs)
- {
- super(context, attrs);
- }
- /**
- * 重写的onMeasure方法
- */
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
- {
- int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
- MeasureSpec.AT_MOST);
- super.onMeasure(widthMeasureSpec, expandSpec);
- }
- }
ListView的item布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="1dip"
- android:layout_marginBottom="1dip"
- android:orientation="vertical"
- android:baselineAligned="false"
- android:background="#ffffff"
- >
- <RelativeLayout
- android:id="@+id/list_rel"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip"
- >
- <ImageView
- android:id="@+id/list_img_icon"
- android:layout_width="3dip"
- android:layout_height="17dip"
- android:layout_marginLeft="15dip"
- android:contentDescription="@null"
- android:scaleType="fitXY"
- android:layout_centerVertical="true"
- android:src="@drawable/selected_orange"
- android:visibility="visible" />
- <TextView
- android:id="@+id/list_txt_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@+id/list_img_icon"
- android:layout_marginLeft="7dip"
- android:layout_marginRight="7dip"
- android:gravity="center"
- android:layout_centerVertical="true"
- android:singleLine="true"
- />
- </RelativeLayout>
- <com.example.gridinlist.MyGridView
- android:id="@+id/list_grid"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_marginBottom="1dip"
- android:columnWidth="70dip"
- android:horizontalSpacing="10dip"
- android:verticalSpacing="10dip"
- android:listSelector="@android:color/transparent"
- android:numColumns="4"
- android:paddingLeft="15dip"
- android:paddingRight="15dip"
- android:scrollbars="none"
- android:stretchMode="columnWidth"
- android:visibility="visible" >
- </com.example.gridinlist.MyGridView>
- <com.example.gridinlist.MyGridView
- android:id="@+id/list_grid_more"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="1dip"
- android:columnWidth="70dip"
- android:horizontalSpacing="10dip"
- android:verticalSpacing="10dip"
- android:listSelector="@android:color/transparent"
- android:numColumns="4"
- android:paddingLeft="15dip"
- android:paddingRight="15dip"
- android:scrollbars="none"
- android:stretchMode="columnWidth"
- android:visibility="gone" >
- </com.example.gridinlist.MyGridView>
- </LinearLayout>
里面包含一个标题,以及两个自写的GridView(一个显示前面部分,另一个显示剩下的,点击展开与折叠其实就是第二个GridView的显示与隐藏)
GridView的item布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <TextView
- android:id="@+id/ItemText"
- android:layout_width="70dip"
- android:layout_height="32dip"
- android:background="@drawable/btn_txt_bg"
- android:text=""
- android:gravity="center"
- />
- </RelativeLayout>
只是简单的一个TextView,用户想扩展或丰富可自行修改。
代码下载连接:http://download.csdn.net/detail/duguju/9233759
listview嵌套gridview,并实现grid元素部分显示以及点击展开与折叠的更多相关文章
-
ListView嵌套GridView显示不完整的解决方案
转载注明出处:http://blog.csdn.net/allen315410/article/details/40152987 近期在做项目中,有个模块须要在ListView中嵌套一个GridVie ...
-
Flutter中用ListView嵌套GridView报错异常
flutter中的ListView组件和GridView组件都是常用的布局组件,有时候ListView中需要嵌套GridView来使用,例如下图: 这种情况就需要在ListView里面再嵌套一个Gri ...
-
android listView嵌套gridview的使用心得
在开发的过程中可能需要用到listview嵌套gridview的场景,但是在Android中, 不能在一个拥有Scrollbar的组件中嵌入另一个拥有Scrollbar的组件,因为这不科学,会混淆滑动 ...
-
ScrollView嵌套ListView嵌套GridView的上下拉以及加载更多
ScrollView 效果 ScrollView 说明 一个ScrollView 嵌套ListView 嵌套GridView的上拉加载更多,下拉刷新的demo. 主要是重写了GridView和Lsit ...
-
ListView嵌套GridView
首先,我们通过两个实例来了解下本篇文章所讲的重点,看下图: 微博: 陌陌: 大家应该对这两款软件并不陌生,接下来,我将列举下本文将要实现的几个点: 1.ListView嵌套GridView,互不冲突, ...
-
ListView嵌套GridView,显示不全解决办法
ListView嵌套GridView时,遇到了GridView只显示一行,其余都显示不出来的问题,最终解决办法如下: 需要自定义GridView,重新绘制高度即可: public class MyGr ...
-
ListView嵌套GridView使用详解及注意事项
ListView嵌套GridView即ListView的每个Item中都包含一个GridView:需要注意的是由于ListView和GridView都是可滑动的控件. 所以需要自定义GridView, ...
-
【Android】listview 嵌套gridview报错,代码:”during second layout pass: posting in next frame
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 公众号:程序员小冰 说明:本人曾经在listview嵌套gridview出现 ...
-
Android中ListView嵌套GridView的简单消息流UI(解决宽高问题)
最近搞一个项目,需要用到类似于新浪微博的消息流,即每一项有文字.有九宫格图片,因此这就涉及到ListView或者ScrollView嵌套GridView的问题.其中GridView的高度问题在网上都很 ...
随机推荐
-
Jtable 表格按多列排序(支持中文汉字排序)
这两天公司让做一个Jtable表格的排序,首先按A列排序,在A列相等时按B列排序,B列相等时按C列排序,ABC三列可以任意指定,最多分三列,这样的一个需求.由于我是大神,所以必须做了出来.ok,不自恋 ...
-
在MySQL中,如何计算一组数据的中位数?
要得到一组数据的中位数(例如某个地区或某家公司的收入中位数),我们首先要将这一任务细分为3个小任务: 将数据排序,并给每一行数据给出其在所有数据中的排名. 找出中位数的排名数字. 找出中间排名对应的值 ...
-
Java中的流
一.Java中流的原理 流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以“流”的方式进行.设备可以是文件,网络,内存等. 四种基本流InputStream,Ou ...
-
mui H5 js动态添加不同类型的数据
html页面需要添加的页面的数据格式 <ul class="mui-table-view" id="OA_task_1"> <li class ...
-
动软代码生成器三层用于winform
DBUtility项目中的DbHelperSQL.cs (找自己对应的数据库类型) 修改前20行中的数据库连接字符串获取方式为: //数据库连接字符串(web.config来配置),多数据库可使用Db ...
-
zookeeper基本原理及适用场景 转:http://blog.chinaunix.net/uid-26748613-id-4536290.html
1.1 zookeeper简介 Zookeeper 是 Hadoop 生态系统中的协同实现,是Hadoop集群管理的一个必不可少的模块,它主要来控制集群中的数据,如它管理Hadoop集群中的NameN ...
-
node项目运行报错
Cannot find module 'webpack/bin/config-optimist' 在项目里面运行npm i webpack-dev-server Cannot find module ...
-
爬虫之requests请求库高级应用
1.SSL Cert Verification #证书验证(大部分网站都是https) import requests respone=requests.get('https://www.12306. ...
-
Oracle的一些经典SQL面试题
实例1:测试数据: create table nba( team varchar2(20), year number(4) ) SQL> select * from nba; TEAM ...
-
[development][lockless][dpdk] 无锁队列
dpdk: http://dpdk.org/doc/guides/prog_guide/ring_lib.html#ring-library linux: https://lwn.net/Articl ...