前言
此篇文章只是本人学习 ExpandableListView 控件使用的笔记,如有雷同,纯属缘分!
首先我们来了解什么是 ExpandableListView ?
官方直译 (无需翻墙):
A view that shows items in a vertically scrolling two-level list. This differs from the ListView by allowing two levels: groups which can individually be expanded to show its children. The items come from the ExpandableListAdapter associated with this view
(一种用于垂直滚动展示两级列表的视图,和ListView的不同之处就是它可以展示两级列表,分组可以单独展开显示子选项。这些选项的数据是通过ExpandableListAdapter关联的)
本人理解:一个可以展示两级列表的试图,并且可以收缩子选项的控件,类似与 QQ 好友列表那种!
还是一言不合就上图
上面的效果是不是和一般的 ExpandableListView 不一样呀!这次的 ExpandableListView 控件的子项是横向的。现在我们就来实现上面的效果!
如果想实现原始的 ExpandableListView 请看下面的文章
Android ExpandableListView使用小结(一)
http://www.open-open.com/lib/view/open1406014566679.html
Now,我们来实现上面的效果:
第一步 创建 activity_main 布局文件 里面包含 ExpandableListView:
activity_main.xml
<?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">
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:groupIndicator="@null"/>
</RelativeLayout>
上面的布局就是一个简单 ExpandableListView 并没有什么多余的属性,如果想了解更多属性请点击 传送门 传送到官网!
第二步 定义定义 MainActivity
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExpandableListView expandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
//自定义适配器
MeExpandableListAdapter mExpandableListAdapter = new MeExpandableListAdapter(MainActivity.this) ;
expandableListView.setAdapter(mExpandableListAdapter);
//默认展开的是那个
groupexpandableListView.expandGroup(0);
}
}
MainActivity 中的代码很简单,主要的代码还是在自定义适配器 MeExpandableListAdapter 那里,现在我们来实现它。
第三步 实现自定义 MeExpandableListAdapter
(1) ExpandableListView 控件是由有分组视图(group)和子选项视图(child)组成的,所以现在先来定义它的分组视图(group)和子选项视图(child):
a.定义分组视图(group)
expandablelistview_group.xml
<?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="wrap_content">
<ImageView
android:id="@+id/group_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"/>
<TextView
android:id="@+id/group_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_toEndOf="@id/group_icon"
android:text=""
android:textColor="#000000"
android:textSize="20sp"/>
<ImageView
android:id="@+id/group_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="5dp"/>
</RelativeLayout>
上面就是分组视图(group)的布局文件就是一个图标+标题+收缩图标,你也可以自己定义这个布局;
b.定义子选项视图(child)
expandablelistview_child.xml
<?xml version="1.0" encoding="utf-8"?>
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/child_gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeeeee"
android:numColumns="4"/>
在子选项视图(child)中我选择以一个 GridView 控件 这样我就能横向的显示子选项视图(child);
c.定义子选项视图(child)中 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="wrap_content"
android:layout_centerInParent="true">
<ImageView
android:id="@+id/child_gridview_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerHorizontal="true"
android:contentDescription="@string/app_name"/>
<TextView
android:id="@+id/child_gridview_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/child_gridview_icon"
android:layout_centerHorizontal="true"
android:layout_marginTop="3dp"
android:text=""
android:textColor="#000000"
android:textSize="15sp"/>
</RelativeLayout>
到现在我们把自定义适配器相关的布局都写好了,我们就来实现 MeExpandableListAdapter
(2)自定义 ExpandableListView的适配器 MeExpandableListAdapter (代码略长)
MeExpandableListAdapter.java
public class MeExpandableListAdapter extends BaseExpandableListAdapter {
//分组视图(group)的标题
private String[] group = {"group1", "group2"};
//分组视图(group)的图标
private int[] groupicon = {R.mipmap.group_icon_1, R.mipmap.group_icon_2};
//子选项视图(child) 的标题
private String[][] gridViewChild = {{"child11", "child12"}, {"child21", "child22"}};
//子选项视图(child) 的图标
private int[][] gridImgChild = new int[][]{
{R.mipmap.ic_launcher, R.mipmap.ic_launcher},
{R.mipmap.ic_launcher, R.mipmap.ic_launcher}
};
private String[][] child = {{""}, {""}};
private LayoutInflater mInflater;
private Context context;
public MeExpandableListAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.context = context;
}
//expandablelistview的分组数
@Override
public int getGroupCount() {
return group.length;
}
//取得指定分组的子元素数
@Override
public int getChildrenCount(int groupPosition) {
return child[groupPosition].length;
}
//取得与给定分组关联的数据
@Override
public Object getGroup(int groupPosition) {
return group[groupPosition];
}
//取得与给定子分组关联的数据
@Override
public Object getChild(int groupPosition, int childPosition) {
return child[groupPosition][childPosition];
}
//取得指定分组的ID.该组ID必须在组中是唯一的.必须不同于其他所有ID(分组及子项目的ID)
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
//取得给定分组中给定子视图的ID. 该组ID必须在组中是唯一的.必须不同于其他所有ID(分组及子项目的ID)
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
//重写GroupView的布局
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
mViewChild = new ViewChild();
convertView = mInflater.inflate(R.layout.expandablelistview_group, parent, false);
mViewChild.textView = (TextView) convertView.findViewById(R.id.group_name);
mViewChild.imageView = (ImageView) convertView.findViewById(R.id.group_indicator);
mViewChild.imageHead = (ImageView) convertView.findViewById(R.id.group_icon);
convertView.setTag(mViewChild);
} else {
mViewChild = (ViewChild) convertView.getTag();
}
if (isExpanded)
mViewChild.imageView.setImageResource(R.mipmap.group_indicator_2);
else
mViewChild.imageView.setImageResource(R.mipmap.group_indicator_1);
mViewChild.textView.setText(getGroup(groupPosition).toString());
mViewChild.imageHead.setImageResource(groupicon[groupPosition]);
return convertView;
}
//重写ChildView的布局
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
mViewChild = new ViewChild();
convertView = mInflater.inflate(R.layout.expandablelistview_chilld, parent, false);
mViewChild.gridView = (GridView) convertView.findViewById(R.id.child_gridView);
convertView.setTag(mViewChild);
} else {
mViewChild = (ViewChild) convertView.getTag();
}
SimpleAdapter mSimpleAdapter = new SimpleAdapter(context,
setGridViewData(gridViewChild[groupPosition],
gridImgChild[groupPosition]),
R.layout.chilld_gridview_item, new String[]{
"child_gridview_item", "child_gridview_img1"},
new int[]{R.id.child_gridview_item,
R.id.child_gridview_icon});
mViewChild.gridView.setAdapter(mSimpleAdapter);
setGridViewListener(mViewChild.gridView, groupPosition);
return convertView;
}
//设置GridView点击事件监听
private void setGridViewListener(final GridView gridView, final int groupPosition) {
gridView.setOnItemClickListener(new GridView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
RelativeLayout ff = (RelativeLayout) view;
TextView gg = (TextView) ff
.findViewById(R.id.child_gridview_item);
Toast.makeText(context, "你点击了" + gg.getText().toString(), Toast.LENGTH_SHORT).show();
}
});
}
//设置GridView数据
private ArrayList<HashMap<String, Object>> setGridViewData(String[] data, int[] img) {
ArrayList<HashMap<String, Object>> gridItem = new ArrayList<>(); for (int i = 0; i < data.length; i++) {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("child_gridview_item", data[i]);
hashMap.put("child_gridview_img1", img[i]);
gridItem.add(hashMap);
}
return gridItem;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
ViewChild mViewChild;
static class ViewChild {
ImageView imageHead;
ImageView imageView;
TextView textView;
GridView gridView;
}
}
上面的代码都有注释,相信大家都看得懂。到此,我们就实现了 ExpandableListView 控件的子项是横向的效果。
总结
其实这次 ExpandableListVie 效果实现主要的就是自定义 BaseExpandableListAdapter 中 getChildView() 的方法,只要把 子选项视图换为一个 GridView 布局就行了(我想:如果子选项视图换成其他控件也行,下次试试)。