ExpandableListView简单应用及listview模拟ExpandableListView
首先我们还是来看一些案例,还是拿搜狐新闻客户端,因为我天天上下班没事爱看这个东东,上班又没时间看新闻,上下班路途之余浏览下新闻打发时间嘛.
看这个效果挺棒吧,其实实现起来也不难,我简单说明下.
首先我们用到的控件是: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了.
效果图:
嗯,效果还可以吧,就介绍这么多了,如有问题或好的建议请吉留言.
- JDK1.8源码(五)——java.util.ArrayList 类
- 代码审计入门总结
- ubuntu mysql启动|停止|重启
- JDK1.8源码(四)——java.util.Arrays 类
- JDK1.8源码(三)——java.lang.String 类
- JDK1.8源码(二)——java.lang.Integer 类
- Java关键字——instanceof
- 【强势推荐】一款可扫描CVE的工具
- Java的深拷贝和浅拷贝
- Java关键字——native
- JDK1.8源码(一)——java.lang.Object类
- Java数据结构和算法(十四)——堆
- Java数据结构和算法(十五)——无权无向图
- Java数据结构和算法(十三)——哈希表
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【8】进大厂必须掌握的面试题-Java面试-异常和线程
- 魔法引用函数magic_quotes_gpc和magic_quotes_runtime的区别和用法
- 在网页中动态的生成一个gif图片
- 在 Visual Basic .NET 或 JScript 代码中使用早期绑定
- 腾讯云TKE-GPU案例: TensorFlow 在TKE中的使用
- 使用pyppeteer 下载chromium 报错 或速度慢
- layui数据表格自定义每页条数limit设置
- dotnet OpenXML 幻灯片 PPTX 的 Slide Id 和页面序号的关系
- springboot 国际化
- Windows/Android/iOS全平台支持的视频播放器EasyPlayerPro,iOS版播放无音频问题如何解决?
- java之springboot之快速入门(一)- maven方式创建项目
- java之springboot之快速入门-Spring Initializr方式创建项目
- springboot之Web综合开发
- springboot之mybatis
- springboot之mybatis多数据源最简解决方案