首先我们还是来看一些案例,还是拿搜狐新闻客户端,因为我天天上下班没事爱看这个东东,上班又没时间看新闻,上下班路途之余浏览下新闻打发时间嘛.
看这个效果挺棒吧,其实实现起来也不难,我简单说明下.
首先我们用到的控件是: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>
/*** * 数据源 * * @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 } } }
效果:
上面模拟显示的孩子是一个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了.
效果图:
嗯,效果还可以吧,就介绍这么多了,如有问题或好的建议请吉留言.