LIstView模拟ExpandableListView

使用ListView模拟ExpandableListView
本文介绍了如何使用ListView实现ExpandableListView的功能,包括布局设计、数据源管理、子项显示控制及焦点问题解决。

/********************************LIstView模拟ExpandableListView**************************************************************/

下面我们看一个案例:

       eyeandroid.com52313260027476.png

2012-9-25 23:28 上传
下载附件 (169.28 KB)
          eyeandroid.com52313260027477.png
2012-9-25 23:28 上传
下载附件 (166.76 KB)

其实就是:点击listview的一个item,展开其孩子,点击另一个item,打开其孩子,关闭之前那个孩子.

这个眨一看是ExpandableListView这个东东,可是本人比较笨戳,整了好久没有弄出来,最终放弃,google下,发现有人用listview来模拟实现,也就跟着做了下.

布局文件:(后面多个隐藏text.)

java代码 复制代码
  1. <?xml version="1.0"encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:background="@color/white"
  6. android:gravity="center_vertical"
  7. android:orientation="vertical">
  8. <RelativeLayout
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:background="@drawable/selector_group"
  12. android:gravity="center_vertical"
  13. android:orientation="horizontal"
  14. android:padding="5dp">
  15. <TextView
  16. android:id="@+id/group"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:layout_centerVertical="true"
  20. android:textColor="@color/black"/>
  21. <ImageView
  22. android:id="@+id/image"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:layout_alignParentRight="true"
  26. android:layout_centerVertical="true"
  27. android:src=http://blog.youkuaiyun.com/jj120522/article/details/"@drawable/collapse" />
  28. </RelativeLayout>
  29. <TextView
  30. android:id="@+id/hint_item"
  31. android:layout_width="fill_parent"
  32. android:layout_height="wrap_content"
  33. android:gravity="center_vertical"
  34. android:padding="10dp"
  35. android:textColor="@color/black"
  36. android:visibility="gone"/>
  37. </LinearLayout>
<?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="wrap_content"
    android:background="@color/white"
    android:gravity="center_vertical"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/selector_group"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="5dp" >

        <TextView
            android:id="@+id/group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:textColor="@color/black" />

        <ImageView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:src=http://blog.youkuaiyun.com/jj120522/article/details/"@drawable/collapse" />
    </RelativeLayout>

    <TextView
        android:id="@+id/hint_item"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:padding="10dp"
        android:textColor="@color/black"
        android:visibility="gone" />

</LinearLayout>

MyAdpter.java

java代码 复制代码
  1. /***
  2. * 数据源
  3. *
  4. * @author zhangjia
  5. *
  6. */
  7. classMyAdpter extendsBaseAdapter {
  8. privateContext context;
  9. privateLayoutInflater inflater;
  10. privateintchange_index = -1;// 改变项
  11. publicMyAdpter(Context context) {
  12. super();
  13. this.context = context;
  14. inflater = (LayoutInflater) context
  15. .getSystemService(context.LAYOUT_INFLATER_SERVICE);
  16. }
  17. @Override
  18. publicintgetCount() {
  19. returngroupList.size();
  20. }
  21. @Override
  22. publicObject getItem(intposition) {
  23. returngroupList.get(position);
  24. }
  25. @Override
  26. publiclonggetItemId(intposition) {
  27. returnposition;
  28. }
  29. @Override
  30. publicView getView(intposition, View convertView, ViewGroup parent) {
  31. GroupHolder groupHolder = null;
  32. if(convertView == null) {
  33. groupHolder = newGroupHolder();
  34. convertView = inflater.inflate(R.layout.group, null);
  35. groupHolder.textView = (TextView) convertView
  36. .findViewById(R.id.group);
  37. groupHolder.imageView = (ImageView) convertView
  38. .findViewById(R.id.image);
  39. groupHolder.hint_item = (TextView) convertView
  40. .findViewById(R.id.hint_item);
  41. convertView.setTag(groupHolder);
  42. } else{
  43. groupHolder = (GroupHolder) convertView.getTag();
  44. }
  45. groupHolder.textView.setText(groupList.get(position));
  46. groupHolder.hint_item.setText(childList.get(position));
  47. if(change_index == position)
  48. groupHolder.hint_item.setVisibility(View.VISIBLE);
  49. else
  50. groupHolder.hint_item.setVisibility(View.GONE);
  51. returnconvertView;
  52. }
  53. /***
  54. * 这个方法用于更改子item的状态
  55. */
  56. publicvoidchangeImageVisable(View view, intposition) {
  57. // 隐藏提示
  58. if(change_index == position) {
  59. GroupHolder groupHolder = (GroupHolder) view.getTag();
  60. if(groupHolder.hint_item.getVisibility() == View.VISIBLE)
  61. groupHolder.hint_item.setVisibility(View.GONE);
  62. else
  63. groupHolder.hint_item.setVisibility(View.VISIBLE);
  64. } else{
  65. change_index = position;
  66. notifyDataSetChanged();// restart getview
  67. }
  68. }
  69. }
/***
	 * 数据源
	 * 
	 * @author zhangjia
	 * 
	 */
	class MyAdpter extends BaseAdapter {
		private Context context;
		private LayoutInflater inflater;

		private int change_index = -1;// 改变项

		public MyAdpter(Context context) {
			super();
			this.context = context;
			inflater = (LayoutInflater) context
					.getSystemService(context.LAYOUT_INFLATER_SERVICE);
		}

		@Override
		public int getCount() {
			return groupList.size();
		}

		@Override
		public Object getItem(int position) {
			return groupList.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			GroupHolder groupHolder = null;
			if (convertView == null) {
				groupHolder = new GroupHolder();
				convertView = inflater.inflate(R.layout.group, null);
				groupHolder.textView = (TextView) convertView
						.findViewById(R.id.group);
				groupHolder.imageView = (ImageView) convertView
						.findViewById(R.id.image);
				groupHolder.hint_item = (TextView) convertView
						.findViewById(R.id.hint_item);
				convertView.setTag(groupHolder);
			} else {
				groupHolder = (GroupHolder) convertView.getTag();
			}
			groupHolder.textView.setText(groupList.get(position));
			groupHolder.hint_item.setText(childList.get(position));
			if (change_index == position)
				groupHolder.hint_item.setVisibility(View.VISIBLE);
			else
				groupHolder.hint_item.setVisibility(View.GONE);

			return convertView;
		}

		/***
		 * 这个方法用于更改子item的状态
		 */
		public void changeImageVisable(View view, int position) {
			// 隐藏提示
			if (change_index == position) {
				GroupHolder groupHolder = (GroupHolder) view.getTag();
				if (groupHolder.hint_item.getVisibility() == View.VISIBLE)
					groupHolder.hint_item.setVisibility(View.GONE);
				else
					groupHolder.hint_item.setVisibility(View.VISIBLE);

			} else {
				change_index = position;
				notifyDataSetChanged();// restart getview
			}

		}
	}

这个数据源很简单,只是多了个用于控制孩子隐藏与显示的方法changeImageVisable.代码很简单,相信不用过多解释.

效果:

     eyeandroid.com52313260027478.png

2012-9-25 23:28 上传
下载附件 (25.87 KB)
        eyeandroid.com52313260027479.png
2012-9-25 23:28 上传
下载附件 (26.42 KB)
        eyeandroid.com523132600274710.png
2012-9-25 23:28 上传
下载附件 (27.68 KB)
    


上面模拟显示的孩子是一个textview(缺点:隐藏textview显示时候点击会影响到其父控件,大家尝试一下,不过肯定有解决办法的.),

下面我来介绍下,如果孩子是listview应该怎么办.


首先配置文件:

java代码 复制代码
  1. <?xml version="1.0"encoding="utf-8"?>
  2. <!-- android:descendantFocusability="blocksDescendants"这个属性就可以让父listview获取焦点 -->
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:background="@color/white"
  7. android:descendantFocusability="blocksDescendants"
  8. android:gravity="center_vertical"
  9. android:orientation="vertical">
  10. <RelativeLayout
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:background="@drawable/selector_group"
  14. android:gravity="center_vertical"
  15. android:orientation="horizontal"
  16. android:padding="5dp">
  17. <TextView
  18. android:id="@+id/group"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:layout_centerVertical="true"
  22. android:text="精品推荐"
  23. android:textColor="@color/black"/>
  24. <ImageView
  25. android:id="@+id/image"
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:layout_alignParentRight="true"
  29. android:layout_centerVertical="true"
  30. android:src=http://blog.youkuaiyun.com/jj120522/article/details/"@drawable/collapse" />
  31. </RelativeLayout>
  32. <ListView
  33. android:id="@+id/hint_item"
  34. android:layout_width="fill_parent"
  35. android:layout_height="wrap_content"
  36. android:gravity="center_vertical"
  37. android:textColor="@color/black"/>
  38. </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- android:descendantFocusability="blocksDescendants"这个属性就可以让父listview获取焦点 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:descendantFocusability="blocksDescendants"
    android:gravity="center_vertical"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/selector_group"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="5dp" >

        <TextView
            android:id="@+id/group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="精品推荐"
            android:textColor="@color/black" />

        <ImageView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:src=http://blog.youkuaiyun.com/jj120522/article/details/"@drawable/collapse" />
    </RelativeLayout>

    <ListView
        android:id="@+id/hint_item"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:textColor="@color/black" />

</LinearLayout>

java代码 复制代码
  1. /***
  2. * InitData
  3. */
  4. voidInitData() {
  5. groupList = newArrayList<String>();
  6. groupList.add("Ios");
  7. groupList.add("Android");
  8. groupList.add("Window");
  9. childList = newArrayList<ArrayList<String>>();
  10. for(inti = 0; i < groupList.size(); i++) {
  11. ArrayList<String> childTemp;
  12. if(i == 0) {
  13. childTemp = newArrayList<String>();
  14. childTemp.add("iphone 4");
  15. childTemp.add("iphone 5");
  16. } elseif(i == 1) {
  17. childTemp = newArrayList<String>();
  18. childTemp.add("Anycall");
  19. childTemp.add("HTC");
  20. childTemp.add("Motorola");
  21. } else{
  22. childTemp = newArrayList<String>();
  23. childTemp.add("Lumia 800C ");
  24. }
  25. childList.add(childTemp);
  26. }
  27. }
	/***
	 * InitData
	 */
	void InitData() {
		groupList = new ArrayList<String>();
		groupList.add("Ios");
		groupList.add("Android");
		groupList.add("Window");
		childList = new ArrayList<ArrayList<String>>();
		for (int i = 0; i < groupList.size(); i++) {
			ArrayList<String> childTemp;
			if (i == 0) {
				childTemp = new ArrayList<String>();
				childTemp.add("iphone 4");
				childTemp.add("iphone 5");
			} else if (i == 1) {
				childTemp = new ArrayList<String>();
				childTemp.add("Anycall");
				childTemp.add("HTC");
				childTemp.add("Motorola");
			} else {
				childTemp = new ArrayList<String>();
				childTemp.add("Lumia 800C ");
			}
			childList.add(childTemp);
		}
	}

java代码 复制代码
  1. /***
  2. * 父数据源
  3. *
  4. * @author zhangjia
  5. *
  6. */
  7. classMyAdpter extendsBaseAdapter {
  8. privateContext context;
  9. privateLayoutInflater inflater;
  10. privateintchange_index = -1;// 改变项
  11. publicMyAdpter(Context context) {
  12. super();
  13. this.context = context;
  14. inflater = (LayoutInflater) context
  15. .getSystemService(context.LAYOUT_INFLATER_SERVICE);
  16. }
  17. @Override
  18. publicintgetCount() {
  19. returngroupList.size();
  20. }
  21. @Override
  22. publicObject getItem(intposition) {
  23. returngroupList.get(position);
  24. }
  25. @Override
  26. publiclonggetItemId(intposition) {
  27. returnposition;
  28. }
  29. @Override
  30. publicView getView(finalintposition, View convertView,
  31. ViewGroup parent) {
  32. GroupHolder groupHolder = null;
  33. if(convertView == null) {
  34. groupHolder = newGroupHolder();
  35. convertView = inflater.inflate(R.layout.group_item, null);
  36. groupHolder.textView = (TextView) convertView
  37. .findViewById(R.id.group);
  38. groupHolder.imageView = (ImageView) convertView
  39. .findViewById(R.id.image);
  40. groupHolder.hint_item = (ListView) convertView
  41. .findViewById(R.id.hint_item);
  42. convertView.setTag(groupHolder);
  43. } else{
  44. groupHolder = (GroupHolder) convertView.getTag();
  45. }
  46. groupHolder.textView.setText(groupList.get(position));
  47. groupHolder.hint_item.setAdapter(getListView(childList
  48. .get(position)));
  49. groupHolder.hint_item
  50. .setOnItemClickListener(newOnItemClickListener() {
  51. @Override
  52. publicvoidonItemClick(AdapterView<?> parent,
  53. View view, intposition_id, longid) {
  54. Toast.makeText(context,
  55. childList.get(position).get(position_id), 1)
  56. .show();
  57. }
  58. });
  59. // 动态设置listview 的高度
  60. setListViewHeightBaseOnChildren(groupHolder.hint_item);
  61. if(change_index == position) {
  62. groupHolder.hint_item.setVisibility(View.VISIBLE);
  63. groupHolder.imageView.setImageResource(R.drawable.expanded);
  64. }
  65. else{
  66. groupHolder.hint_item.setVisibility(View.GONE);
  67. groupHolder.imageView.setImageResource(R.drawable.collapse);
  68. }
  69. returnconvertView;
  70. }
  71. /***
  72. * 这个方法用于更改子item的状态
  73. */
  74. publicvoidchangeImageVisable(View view, intposition) {
  75. // 隐藏提示
  76. if(change_index == position) {
  77. GroupHolder groupHolder = (GroupHolder) view.getTag();
  78. if(groupHolder.hint_item.getVisibility() == View.VISIBLE)
  79. groupHolder.hint_item.setVisibility(View.GONE);
  80. else
  81. groupHolder.hint_item.setVisibility(View.VISIBLE);
  82. } else{
  83. change_index = position;
  84. notifyDataSetChanged();// restart getview
  85. }
  86. }
  87. }
/***
	 * 父数据源
	 * 
	 * @author zhangjia
	 * 
	 */
	class MyAdpter extends BaseAdapter {
		private Context context;
		private LayoutInflater inflater;

		private int change_index = -1;// 改变项

		public MyAdpter(Context context) {
			super();
			this.context = context;
			inflater = (LayoutInflater) context
					.getSystemService(context.LAYOUT_INFLATER_SERVICE);
		}

		@Override
		public int getCount() {
			return groupList.size();
		}

		@Override
		public Object getItem(int position) {
			return groupList.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(final int position, View convertView,
				ViewGroup parent) {
			GroupHolder groupHolder = null;
			if (convertView == null) {
				groupHolder = new GroupHolder();
				convertView = inflater.inflate(R.layout.group_item, null);
				groupHolder.textView = (TextView) convertView
						.findViewById(R.id.group);
				groupHolder.imageView = (ImageView) convertView
						.findViewById(R.id.image);
				groupHolder.hint_item = (ListView) convertView
						.findViewById(R.id.hint_item);

				convertView.setTag(groupHolder);
			} else {
				groupHolder = (GroupHolder) convertView.getTag();
			}
			groupHolder.textView.setText(groupList.get(position));
			groupHolder.hint_item.setAdapter(getListView(childList
					.get(position)));
			groupHolder.hint_item
					.setOnItemClickListener(new OnItemClickListener() {
						@Override
						public void onItemClick(AdapterView<?> parent,
								View view, int position_id, long id) {
							Toast.makeText(context,
									childList.get(position).get(position_id), 1)
									.show();
						}
					});
			// 动态设置listview 的高度
			setListViewHeightBaseOnChildren(groupHolder.hint_item);

			if (change_index == position) {
				groupHolder.hint_item.setVisibility(View.VISIBLE);
				groupHolder.imageView.setImageResource(R.drawable.expanded);
			}

			else {
				groupHolder.hint_item.setVisibility(View.GONE);
				groupHolder.imageView.setImageResource(R.drawable.collapse);
			}

			return convertView;
		}

		/***
		 * 这个方法用于更改子item的状态
		 */
		public void changeImageVisable(View view, int position) {
			// 隐藏提示
			if (change_index == position) {
				GroupHolder groupHolder = (GroupHolder) view.getTag();
				if (groupHolder.hint_item.getVisibility() == View.VISIBLE)
					groupHolder.hint_item.setVisibility(View.GONE);
				else
					groupHolder.hint_item.setVisibility(View.VISIBLE);
			} else {
				change_index = position;
				notifyDataSetChanged();// restart getview
			}

		}
	}
上面代码和刚才的差不多,唯一需要我们注意的是“ listview嵌套listview,我们需要注意哪些问题”.

第一:listview和listview嵌套,子listview只显示一个多一点点,不能正常显示,解决办法:对listview重新设置起高度.(相信同学们对这个方法一点也不陌生.)

java代码 复制代码
  1. /***
  2. * 动态设置listview的高度
  3. *
  4. * @param listView
  5. */
  6. publicvoidsetListViewHeightBaseOnChildren(ListView listView) {
  7. ListAdapter listAdapter = listView.getAdapter();
  8. if(listAdapter == null)
  9. return;
  10. inttotalHeight = 0;// 总高度
  11. for(inti = 0; i < listAdapter.getCount(); i++) {
  12. View listitem = listAdapter.getView(i, null, listView);
  13. listitem.measure(0, 0);
  14. totalHeight += listitem.getMeasuredHeight();
  15. }
  16. inttotalDividerHeight = 0;
  17. totalDividerHeight = listView.getDividerHeight()
  18. * (listAdapter.getCount() - 1);
  19. ViewGroup.LayoutParams layoutParams = listView.getLayoutParams();
  20. layoutParams.height = totalHeight + totalDividerHeight;
  21. listView.setLayoutParams(layoutParams);
  22. }
/***
	 * 动态设置listview的高度
	 * 
	 * @param listView
	 */
	public void setListViewHeightBaseOnChildren(ListView listView) {
		ListAdapter listAdapter = listView.getAdapter();
		if (listAdapter == null)
			return;
		int totalHeight = 0;// 总高度
		for (int i = 0; i < listAdapter.getCount(); i++) {
			View listitem = listAdapter.getView(i, null, listView);
			listitem.measure(0, 0);
			totalHeight += listitem.getMeasuredHeight();
		}
		int totalDividerHeight = 0;
		totalDividerHeight = listView.getDividerHeight()
				* (listAdapter.getCount() - 1);
		ViewGroup.LayoutParams layoutParams = listView.getLayoutParams();
		layoutParams.height = totalHeight + totalDividerHeight;
		listView.setLayoutParams(layoutParams);
	}
第二个问题: listview 嵌套listview的时候,子listview会屏蔽掉父listview的焦点.使得父listview无法点击.

解决办法很简单:我们只需要在父listview的Adapter里面的配置文件最顶部的如LinearLayout加入一行:  android:descendantFocusability="blocksDescendants"就ok了. 


效果图:

    eyeandroid.com523132600274711.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值