ExpandableListView是ListView的子类,他在ListView上进行了扩展,它把列表项分成了几组,每组里包含了多个列表项
ExpandableListView的列表项是由ExpandableListAdapter提供的,实现ExpandableListAdapter三种常用方式,常用的ExpandableListAdapter子类如下:
1,扩展BaseExpandableListAdapter实现ExpandableListAdapter
2,使用SimpleExpandableListAdapter将 两个List集合包装成ExpandableListAdapter
3,使用SimpleCursorTreeAdapter将Cursor中的数据包装成SimpleCursorTreeAdapter
ExpandableListAdapter及其子类的继承关系类图看这篇文章讲的比较好,看懂了:http://hubingforever.blog.163.com/blog/static/1710405792010538823477/
ExpandableListView的xml属性:
android:childDivider 指定个组内各子列表项之间的分隔条
android:childIndicator 显示子列表项旁边的Drawble对象
android:groupIndicator 显示组列表项旁边的Drawble对象
ExpandableListView是android中可以实现下拉list的一个控件,是一个垂直滚动的心事两个级别列表项手风琴试图,列表项是来自ExpandableListViewaAdapter,组可以单独展开。
重要方法:
<span style="font-size:24px;">expandGroup (int groupPos) ;//在分组列表视图中 展开一组, setSelectedGroup (int groupPosition) ;//设置选择指定的组。 setSelectedChild (int groupPosition, int childPosition, boolean shouldExpandGroup);//设置选择指定的子项。 getPackedPositionGroup (long packedPosition);//返回所选择的组 getPackedPositionForChild (int groupPosition, int childPosition) ;//返回所选择的子项 getPackedPositionType (long packedPosition);//返回所选择项的类型(Child,Group) isGroupExpanded (int groupPosition);//判断此组是否展开</span>
<span style="font-size:24px;">expandableListView.setDivider();这个是设定每个Group之间的分割线。 expandableListView.setGroupIndicator();这个是设定每个Group之前的那个图标。 expandableListView.collapseGroup(int group); 将第group组收起</span>
一,使用扩展BaseExpandableListAdapter来提供数据源
扩展BaseExpandableListAdapter需要重写11个方法:
* getGroupCount(),返回包含组列表的数量
* getChildrenCount(int groupPosition),返回包含组列表的数量
*
* getGroup(int groupPosition),返回组列表的对象
* getChild(int groupPosition, int childPosition),返回组列表下的子列表对象
*
* getGroupId(int groupPosition),返回组列表Id
* getChildId(int groupPosition, int childPosition),返回祖列表的子列表的Id
* 下面两个属性很重要!
* getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent),该方法决定每个组选项的外观、
* getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent),该方法决定每个子选项的外观、
*isChildSelectable(int groupPosition,
int childPosition):如果child添加监听事件,则要返回true
Main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!--ExpandableListView组件 android:childDivider 指定个组内各子列表项之间的分隔条 android:childIndicator 显示子列表项旁边的Drawble对象 android:groupIndicator 显示组列表项旁边的Drawble对象 --> <ExpandableListView android:id="@+id/expandableListView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:childDivider="#f0f" > </ExpandableListView> </LinearLayout>MainActivity.java
package com.hust.expandablelistview; import android.app.Activity; import android.os.Bundle; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.LayoutParams; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BaseExpandableListAdapter bela=new BaseExpandableListAdapter(){ /*自动实现这10个方法 * getGroupCount(),返回包含组列表的数量 * getChildrenCount(int groupPosition),返回包含组列表的数量 * * getGroup(int groupPosition),返回组列表的对象 * getChild(int groupPosition, int childPosition),返回组列表下的子列表对象 * * getGroupId(int groupPosition),返回组列表Id * getChildId(int groupPosition, int childPosition),返回祖列表的子列表的Id * * getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent),该方法决定每个组选项的外观、 * getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent),该方法决定每个子选项的外观、 * * * */ int[] logos=new int[]{ R.drawable.p,R.drawable.z,R.drawable.t }; //组列表的数量 private String[] armTypes=new String[]{"我的好友","高中同学","大学同学"}; //组列表下的子列表项,可扩展的ExpandableListView是个二维数组 private String[][] arms=new String[][]{ {"狂战士","龙骑士","黑暗圣堂","电兵"}, {"张娜","李四","赵龙","钱爽"}, {"王燕","刘涛","张坦克","汪明城"} }; //返回包含组列表的数量 @Override public int getGroupCount() { // TODO Auto-generated method stub return armTypes.length; } //返回组位置下的子列表项的数量 @Override public int getChildrenCount(int groupPosition) { // TODO Auto-generated method stub return arms[groupPosition].length; } //返回组列表的对象 @Override public Object getGroup(int groupPosition) { // TODO Auto-generated method stub return armTypes[groupPosition]; } //返回组列表下的子列表对象 @Override public Object getChild(int groupPosition, int childPosition) { // TODO Auto-generated method stub return arms[groupPosition][childPosition]; } //返回组列表Id @Override public long getGroupId(int groupPosition) { // TODO Auto-generated method stub return groupPosition; } //返回祖列表的子列表的Id @Override public long getChildId(int groupPosition, int childPosition) { // TODO Auto-generated method stub return childPosition; } @Override public boolean hasStableIds() { // TODO Auto-generated method stub return true; } //该方法决定每个组选项的外观、这里这定义组列表布局,也可以用xml文件 @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { // TODO Auto-generated method stub LinearLayout ll=new LinearLayout(MainActivity.this); ll.setOrientation(0); ImageView logo=new ImageView(MainActivity.this); logo.setImageResource(logos[groupPosition]); TextView textview=getTextView(); textview.setText(getGroup(groupPosition).toString()); ll.addView(logo); ll.addView(textview); return ll; } //设置TextView的参数 private TextView getTextView() { // TODO Auto-generated method stub AbsListView.LayoutParams lp=new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,64); TextView textview=new TextView(MainActivity.this); textview.setLayoutParams(lp);//设置布局参数,android:layout_Width="match_parent",android:layout_Height="64" textview.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT);//android:gravity="CENTER_VERTICAL|LEFT" textview.setPadding(36, 0, 0, 0); textview.setTextSize(16); //android:textsize="20dp" return textview; } //该方法决定每个子选项的外观 @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { // TODO Auto-generated method stub TextView text=getTextView(); text.setText(getChild(groupPosition,childPosition).toString()); return text; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { // TODO Auto-generated method stub return true; } }; ExpandableListView expandablelistview=(ExpandableListView) findViewById(R.id.expandableListView1); //设置adapter expandablelistview.setAdapter(bela); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter( this, gruops, R.drawable.expandablelistview_groups, new String[]{"group"}, new int[]{R.id.textGroup}, childs, R.drawable.expandablelistview_child, new String[]{"child"}, new int[]{R.id.textChild} );* 参数1.上下文对象Context
1,定义一个主界面expandablelistview.xml
<?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="fill_parent" android:orientation="vertical" > <ExpandableListView android:id ="@+id/expandableListView" android:layout_width ="fill_parent" android:layout_height ="wrap_content" > </ExpandableListView> </LinearLayout>2.在res/drawable目录下创建样式文件expandablelistview_groups.xml该界面是组界面:
<?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="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textGroup" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="40px" android:paddingTop="6px" android:paddingBottom="6px" android:textSize="15sp" android:text="No data" > </TextView> </LinearLayout>3.在res/drawable目录下创建样式文件expandablelistview_child.xml;是子控件,直接显示列表内容
<?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="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textChild" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="60px" android:paddingTop="10px" android:paddingBottom="10px" android:textSize="20sp" android:text="No Data" /> </LinearLayout>ExpandableListViewDemo_two.java
public class ExpandableListViewDemo_two extends Activity { /** Called when the activity is first created. */ private ExpandableListView expandableListView_one; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.expandablelistview); expandableListView_one =(ExpandableListView)findViewById(R.id.expandableListView); //创建二个一级条目标题 Map<String, String> title_1 = new HashMap<String, String>(); Map<String, String> title_2 = new HashMap<String, String>(); title_1.put("group", "移动开发"); title_2.put("group", "Web开发"); //创建一级条目容器 List<Map<String, String>> gruops = new ArrayList<Map<String,String>>(); gruops.add(title_1); gruops.add(title_2); //创建二级条目内容 //内容一 Map<String, String> content_1 = new HashMap<String, String>(); Map<String, String> content_2 = new HashMap<String, String>(); content_1.put("child", "ANDROID"); content_2.put("child", "IOS"); List<Map<String, String>> childs_1 = new ArrayList<Map<String,String>>(); childs_1.add(content_1); childs_1.add(content_2); //内容二 Map<String, String> content_3 = new HashMap<String, String>(); Map<String, String> content_4 = new HashMap<String, String>(); Map<String, String> content_5 = new HashMap<String, String>(); content_3.put("child", "jsp"); content_4.put("child", "servlet"); content_5.put("child", "page"); List<Map<String, String>> childs_2 = new ArrayList<Map<String,String>>(); childs_2.add(content_3); childs_2.add(content_4); childs_2.add(content_5); //存放两个内容, 以便显示在列表中 List<List<Map<String, String>>> childs = new ArrayList<List<Map<String,String>>>(); childs.add(childs_1); childs.add(childs_2); //创建ExpandableList的Adapter容器 /** * 使用SimpleExpandableListAdapter显示ExpandableListView * 参数1.上下文对象Context * 参数2.一级条目目录集合 * 参数3.一级条目对应的布局文件 (expandablelistview_groups.xml文件 * 参数4.fromto,就是map中的key,指定要显示的对象 * 参数5.与参数4对应,指定要显示在groups中的id * 参数6.二级条目目录集合 * 参数7.二级条目对应的布局文件 * 参数9.与参数8对应,指定要显示在childs中的id / SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter( this, gruops, R.drawable.expandablelistview_groups, new String[]{"group"}, new int[]{R.id.textGroup}, childs, R.drawable.expandablelistview_child, new String[]{"child"}, new int[]{R.id.textChild} ); //加入列表 expandableListView_one.setAdapter(adapter); expandableListView_one.setOnChildClickListener(listener); } private OnChildClickListener listener =new OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { // TODO Auto-generated method stub toast("点击了"); return false; } }; private void toast(String str) { Toast.makeText(this, str, Toast.LENGTH_LONG).show(); } }上面的样式也可以使用系统的自带的样式如下:
1,继承ExpandableListActivity
2,定义好内容ExpandableListAdapter,扩展BaseExpandableListAdapter和SimpleExpandableListAdapter都可以
3,setListAdapter的方法添加adapter
package com.example.expandablelistactivity; import android.app.ExpandableListActivity; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends ExpandableListActivity//继承ExpandableListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //无需布局文件 //自定义扩展BaseExpandableListAdapter ExpandableListAdapter adapter = new BaseExpandableListAdapter() { int[] logos = new int[] { R.drawable.p, R.drawable.z, R.drawable.t }; //组列表的数量 private String[] armTypes=new String[]{"我的好友","高中同学","大学同学"}; //组列表下的子列表项,可扩展的ExpandableListView是个二维数组 private String[][] arms=new String[][]{ {"狂战士","龙骑士","黑暗圣堂","电兵"}, {"张娜","李四","赵龙","钱爽"}, {"王燕","刘涛","张坦克","汪明城"} }; //获取指定组位置、指定子列表项处的子列表项数据 @Override public Object getChild(int groupPosition, int childPosition) { return arms[groupPosition][childPosition]; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public int getChildrenCount(int groupPosition) { return arms[groupPosition].length; } private TextView getTextView() { AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 64); TextView textView = new TextView(MainActivity.this); textView.setLayoutParams(lp); textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); textView.setPadding(36, 0, 0, 0); textView.setTextSize(16); return textView; } //该方法决定每个子选项的外观 @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { TextView textView = getTextView(); textView.setText(getChild(groupPosition, childPosition).toString()); return textView; } //获取指定组位置处的组数据 @Override public Object getGroup(int groupPosition) { return armTypes[groupPosition]; } @Override public int getGroupCount() { return armTypes.length; } @Override public long getGroupId(int groupPosition) { return groupPosition; } //该方法决定每个组选项的外观 @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { LinearLayout ll = new LinearLayout(MainActivity.this); ll.setOrientation(0); ImageView logo = new ImageView(MainActivity.this); logo.setImageResource(logos[groupPosition]); ll.addView(logo); TextView textView = getTextView(); textView.setText(getGroup(groupPosition).toString()); ll.addView(textView); return ll; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } @Override public boolean hasStableIds() { return true; } }; // 设置该窗口显示列表 setListAdapter(adapter); } }
附上源码更方便学习:
public class ExpandableListActivity extends Activity implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener { ExpandableListAdapter mAdapter; ExpandableListView mList; boolean mFinishedStart = false; /** * Override this to populate the context menu when an item is long pressed. menuInfo * will contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo} * whose packedPosition is a packed position * that should be used with {@link ExpandableListView#getPackedPositionType(long)} and * the other similar methods. * <p> * {@inheritDoc} */ @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { } /** * Override this for receiving callbacks when a child has been clicked. * <p> * {@inheritDoc} */ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { return false; } /** * Override this for receiving callbacks when a group has been collapsed. */ public void onGroupCollapse(int groupPosition) { } /** * Override this for receiving callbacks when a group has been expanded. */ public void onGroupExpand(int groupPosition) { } /** * Ensures the expandable list view has been created before Activity restores all * of the view states. * *@see Activity#onRestoreInstanceState(Bundle) */ @Override protected void onRestoreInstanceState(Bundle state) { ensureList(); super.onRestoreInstanceState(state); } /** * Updates the screen state (current list and other views) when the * content changes. * * @see Activity#onContentChanged() */ @Override public void onContentChanged() { super.onContentChanged(); View emptyView = findViewById(com.android.internal.R.id.empty); mList = (ExpandableListView)findViewById(com.android.internal.R.id.list); if (mList == null) { throw new RuntimeException( "Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'"); } if (emptyView != null) { mList.setEmptyView(emptyView); } mList.setOnChildClickListener(this); mList.setOnGroupExpandListener(this); mList.setOnGroupCollapseListener(this); if (mFinishedStart) { setListAdapter(mAdapter); } mFinishedStart = true; } /** * Provide the adapter for the expandable list. */ public void setListAdapter(ExpandableListAdapter adapter) { synchronized (this) { ensureList(); mAdapter = adapter; mList.setAdapter(adapter); } } /** * Get the activity's expandable list view widget. This can be used to get the selection, * set the selection, and many other useful functions. * * @see ExpandableListView */ public ExpandableListView getExpandableListView() { ensureList(); return mList; } /** * Get the ExpandableListAdapter associated with this activity's * ExpandableListView. */ public ExpandableListAdapter getExpandableListAdapter() { return mAdapter; } private void ensureList() { if (mList != null) { return; } setContentView(com.android.internal.R.layout.expandable_list_content); } /** * Gets the ID of the currently selected group or child. * * @return The ID of the currently selected group or child. */ public long getSelectedId() { return mList.getSelectedId(); } /** * Gets the position (in packed position representation) of the currently * selected group or child. Use * {@link ExpandableListView#getPackedPositionType}, * {@link ExpandableListView#getPackedPositionGroup}, and * {@link ExpandableListView#getPackedPositionChild} to unpack the returned * packed position. * * @return A packed position representation containing the currently * selected group or child's position and type. */ public long getSelectedPosition() { return mList.getSelectedPosition(); } /** * Sets the selection to the specified child. If the child is in a collapsed * group, the group will only be expanded and child subsequently selected if * shouldExpandGroup is set to true, otherwise the method will return false. * * @param groupPosition The position of the group that contains the child. * @param childPosition The position of the child within the group. * @param shouldExpandGroup Whether the child's group should be expanded if * it is collapsed. * @return Whether the selection was successfully set on the child. */ public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) { return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup); } /** * Sets the selection to the specified group. * @param groupPosition The position of the group that should be selected. */ public void setSelectedGroup(int groupPosition) { mList.setSelectedGroup(groupPosition); } }
UI组件之AdapterView及其子类(六)ExpandableListView组件和ExpandableListActivity的使用
原文:http://blog.csdn.net/tuke_tuke/article/details/50532097