现在的位置: 首页 > 综合 > 正文

android ExpandableListView简单应用及listview模拟ExpandableListView

2013年09月21日 ⁄ 综合 ⁄ 共 11672字 ⁄ 字号 评论关闭

       首先我们还是来看一些案例,还是拿搜狐新闻客户端,因为我天天上下班没事爱看这个东东,上班又没时间看新闻,上下班路途之余浏览下新闻打发时间嘛.

                          

看这个效果挺棒吧,其实实现起来也不难,我简单说明下.

首先我们用到的控件是:ExpandableListView

布局文件:

<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" >

    <!--
     android:groupIndicator="@null" 取消默认图片
    android:childIndicatorLeft 设置孩子左边间距
    android:dividerHeight 这个高度一定要设置,不然显示不出来分割线,估计默认为0 吧
     android:childDivider="@drawable/child_bg" 这个直接引color,或者图片会导致整个孩子背景都为这个颜色  ,不知道原因,如果有谁知道,请Give me say.
    -->

    <ExpandableListView
        android:id="@+id/expandablelist"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="@null"
        android:childDivider="@drawable/child_bg"
        android:childIndicatorLeft="0dp"
        android:divider="@color/Grey"
        android:dividerHeight="1dp"
        android:groupIndicator="@null"
        android:scrollbarAlwaysDrawHorizontalTrack="true" >
    </ExpandableListView>

</RelativeLayout>

MyexpandableListAdapter.java

/***
	 * 数据源
	 * 
	 * @author Administrator
	 * 
	 */
	class MyexpandableListAdapter extends BaseExpandableListAdapter {
		private Context context;
		private LayoutInflater inflater;

		public MyexpandableListAdapter(Context context) {
			this.context = context;
			inflater = LayoutInflater.from(context);
		}

		// 返回父列表个数
		@Override
		public int getGroupCount() {
			return groupList.size();
		}

		// 返回子列表个数
		@Override
		public int getChildrenCount(int groupPosition) {
			return childList.get(groupPosition).size();
		}

		@Override
		public Object getGroup(int groupPosition) {

			return groupList.get(groupPosition);
		}

		@Override
		public Object getChild(int groupPosition, int childPosition) {
			return childList.get(groupPosition).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 true;
		}

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded,
				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.textView.setTextSize(15);
				convertView.setTag(groupHolder);
			} else {
				groupHolder = (GroupHolder) convertView.getTag();
			}

			groupHolder.textView.setText(getGroup(groupPosition).toString());
			if (isExpanded)// ture is Expanded or false is not isExpanded
				groupHolder.imageView.setImageResource(R.drawable.expanded);
			else
				groupHolder.imageView.setImageResource(R.drawable.collapse);
			return convertView;
		}

		@Override
		public View getChildView(int groupPosition, int childPosition,
				boolean isLastChild, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.item, null);
			}
			TextView textView = (TextView) convertView.findViewById(R.id.item);
			textView.setTextSize(13);
			textView.setText(getChild(groupPosition, childPosition).toString());
			return convertView;
		}

		@Override
		public boolean isChildSelectable(int groupPosition, int childPosition) {
			return true;
		}
	}

	@Override
	public boolean onGroupClick(final ExpandableListView parent, final View v,
			int groupPosition, final long id) {

		return false;
	}

上面实现起来比较简单.相信对listview熟悉的朋友看这个一定很熟悉,无外乎就是多了个孩子.

selector_group.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/Grey" android:state_pressed="true"></item>
    <item android:drawable="@color/Grey" android:state_selected="true"></item>
    <item android:drawable="@color/LightGray"></item>

</selector>

selector_item.xml  同理.


效果图:

                
    

效果虽然丑了点,不过就是这么回事,至于显示group的item,还是孩子的item,你可以随意定制.

   不想敲的同学,可以下载源码,稍作调整.  

   源码下载



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

下面我们接着看一些案例:

               

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

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

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

<?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="@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

/***
	 * 数据源
	 * 
	 * @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.代码很简单,相信不用过多解释.

效果:

                   
  

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

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

首先配置文件:

<?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="@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>

	/***
	 * 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);
		}
	}

/***
	 * 父数据源
	 * 
	 * @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重新设置起高度.(相信同学们对这个方法一点也不陌生.)

/***
	 * 动态设置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了. 


效果图:

   

嗯,效果还可以吧,就介绍这么多了,如有问题或好的建议请吉留言.


         



抱歉!评论已关闭.