Android之带group指示器的ExpandableListView(自写)_Android

我们都知道Android缺省的ExpandableListView的group header无法固定在界面上,当向下滚动后,不能对当前显示的那些child 指示出它们归属于哪个group,在网上搜了很多关于仿手机QQ好友分组效果的ExpandableListView,发现都不尽如意,于是乎在别人的基础上改进了一点点,其实原理还是差不多的,只是增加了往上挤出去的动画效果,而且更加简单,只不过还是没有完全到达跟QQ一样的效果,希望有高手能实现更加逼真的效果,下面我们先看看效果图:
 
我这里没有把ExpandableListView独立出来形成一个新的控件,跟网上很多朋友一样,监听OnScrollListener事件,当group不是在第一个位置时,就把我们头部的那个indicator显示出来,并且让它的view跟当前child所在group的view一样的,然后再增加一个点击关闭组的事件,即达到了简单的仿QQ好友分组的效果。
下面我们先来看看主要的布局文件:main.xml,下面那个topGroup的FrameLayout就是我们的指示器。

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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" >
</ExpandableListView>
<FrameLayout
android:id="@+id/topGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</FrameLayout>
</FrameLayout>

其中最重要的是下面这部分:我们监听onSroll这个接口事件,当ListView在滑动时,做相应的处理,代码中注释比较多,我这里就不多作说明了。

复制代码 代码如下:

/**
* here is very importance for indicator group
*/
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
final ExpandableListView listView = (ExpandableListView) view;
/**
* calculate point (0,0)
*/
int npos = view.pointToPosition(0, 0);// 其实就是firstVisibleItem
if (npos == AdapterView.INVALID_POSITION)// 如果第一个位置值无效
return;
long pos = listView.getExpandableListPosition(npos);
int childPos = ExpandableListView.getPackedPositionChild(pos);// 获取第一行child的id
int groupPos = ExpandableListView.getPackedPositionGroup(pos);// 获取第一行group的id
if (childPos == AdapterView.INVALID_POSITION) {// 第一行不是显示child,就是group,此时没必要显示指示器
View groupView = listView.getChildAt(npos
- listView.getFirstVisiblePosition());// 第一行的view
indicatorGroupHeight = groupView.getHeight();// 获取group的高度
indicatorGroup.setVisibility(View.GONE);// 隐藏指示器
} else {
indicatorGroup.setVisibility(View.VISIBLE);// 滚动到第一行是child,就显示指示器
}
// get an error data, so return now
if (indicatorGroupHeight == 0) {
return;
}
// update the data of indicator group view
if (groupPos != indicatorGroupId) {// 如果指示器显示的不是当前group
mAdapter.getGroupView(groupPos, listView.isGroupExpanded(groupPos),
indicatorGroup.getChildAt(0), null);// 将指示器更新为当前group
indicatorGroupId = groupPos;
Log.e(TAG, PRE + "bind to new group,group position = " + groupPos);
// mAdapter.hideGroup(indicatorGroupId); // we set this group view
// to be hided
// 为此指示器增加点击事件
indicatorGroup.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
listView.collapseGroup(indicatorGroupId);
}
});
}
if (indicatorGroupId == -1) // 如果此时grop的id无效,则返回
return;
/**
* calculate point (0,indicatorGroupHeight) 下面是形成往上推出的效果
*/
int showHeight = indicatorGroupHeight;
int nEndPos = listView.pointToPosition(0, indicatorGroupHeight);// 第二个item的位置
if (nEndPos == AdapterView.INVALID_POSITION)// 如果无效直接返回
return;
long pos2 = listView.getExpandableListPosition(nEndPos);
int groupPos2 = ExpandableListView.getPackedPositionGroup(pos2);// 获取第二个group的id
if (groupPos2 != indicatorGroupId) {// 如果不等于指示器当前的group
View viewNext = listView.getChildAt(nEndPos
- listView.getFirstVisiblePosition());
showHeight = viewNext.getTop();
Log.e(TAG, PRE + "update the show part height of indicator group:"
+ showHeight);
}
// update group position
MarginLayoutParams layoutParams = (MarginLayoutParams) indicatorGroup
.getLayoutParams();
layoutParams.topMargin = -(indicatorGroupHeight - showHeight);
indicatorGroup.setLayoutParams(layoutParams);
}

本文源码下载
最后跟大家分享一下另外一个仿iPhone通讯录效果的代码。它是ListView的扩展,效果最好。希望有高手能把ExpandableListView扩展成一样的效果。
源码下载

时间: 2024-11-03 21:56:10

Android之带group指示器的ExpandableListView(自写)_Android的相关文章

Android之带group指示器的ExpandableListView(自写)

我们都知道Android缺省的ExpandableListView的group header无法固定在界面上,当向下滚动后,不能对当前显示的那些child 指示出它们归属于哪个group,在网上搜了很多关于仿手机QQ好友分组效果的ExpandableListView,发现都不尽如意,于是乎在别人的基础上改进了一点点,其实原理还是差不多的,只是增加了往上挤出去的动画效果,而且更加简单,只不过还是没有完全到达跟QQ一样的效果,希望有高手能实现更加逼真的效果,下面我们先看看效果图:   我这里没有把E

Android之IphoneTreeView带组指示器的ExpandableListView效果_Android

之前实现过一次这种效果的ExpandableListView:http://www.jb51.net/article/38482.htm,带效果比较挫,最近,在参考联系人源码PinnedHeaderListView,以及网上各位大侠的源码,封装了一个效果最好,而且使用最简单的IphoneTreeView,下面先看看效果图:  首先让我们看看封装得比较完善的IphoneTreeView: 复制代码 代码如下: public class IphoneTreeView extends Expandab

Android之IphoneTreeView带组指示器的ExpandableListView效果

之前实现过一次这种效果的ExpandableListView:http://www.jb51.net/article/38482.htm,带效果比较挫,最近,在参考联系人源码PinnedHeaderListView,以及网上各位大侠的源码,封装了一个效果最好,而且使用最简单的IphoneTreeView,下面先看看效果图:   首先让我们看看封装得比较完善的IphoneTreeView: 复制代码 代码如下: public class IphoneTreeView extends Expanda

api-开发是使用位置服务(android自带API),无法上传实时坐标,只能上传第一个点的坐标?

问题描述 开发是使用位置服务(android自带API),无法上传实时坐标,只能上传第一个点的坐标? 开发是使用位置服务(android自带API),无法上传实时坐标,只能上传第一个点的坐标?有大神知道这是为什么吗?急急急!!! 解决方案 http://blog.csdn.net/qiannuo/article/details/6791873

android自带相机删除预览照片后怎么回到下一张预览而不是回到相机

问题描述 android自带相机删除预览照片后怎么回到下一张预览而不是回到相机 打开照相机----随便照几张照片----照完后照相按钮上方会有刚才照的照片的预览(一个小方框)----点击小方框预览照片----随便删除一张----此后将回到照相界面--怎么改代码让它回到下一张的预览照片? 解决方案 你打开图片是跳转到另一个activity了吗?如果是的话,把 activity的启动方式 可以改为 singleTop,不然你每次打开一张图片就会新建一个activity,这样浪费内存,且会造成你说的后

调用Android自带日历功能(日历列表单、添加一个日历事件)

调用Android自带日历功能  觉得这篇文章不错,转载过来. 转载:http://blog.csdn.net/djy1992/article/details/9948393 Android手机配备有一个内置的日历应用程序.第三方应用程序可以利用日历内容提供商接口读取用户的日历信息和安排在日历新的事件.这个日历可以直接同步用户的谷歌日历.  不幸的是,没有文档和Android手机的日历应用集成,因为有另外一个联系人应用程序.相反,本文所提供的所有信息,将会通过逆向工程的谷歌日历内容提供商.该接口

android 自带webview 加载html5游戏

问题描述 android 自带webview 加载html5游戏 android 自带webview加载html5游戏不流畅,但在微信内置浏览或是UC等浏览器中玩的就很流畅,该怎么样优化webview能像在微信中玩h5游戏一样流畅? 解决方案 自己写webview就算了,看看有没有开源的吧,应该有很多

android wifi direct group owner negotiation

问题描述 android wifi direct group owner negotiation 有人知道android wifi direct 中group owner negotiation 中的哪个device作为GO哪个作为Client以及 采用Pin码还是PBC模式是在哪里确定的吗?

Android自带的webview中加载支付宝成功后没有回调,只停留在了支付宝支付成功页面

问题描述 Android自带的webview中加载支付宝成功后没有回调,只停留在了支付宝支付成功页面 我用Android自带的webview中加载支付宝页面去支付,在js里也配置了回调的return_url,为啥收不着回调呢?只是返回支付宝支付成功的链接,然后就停在支付宝支付完成的页面了. 程序里也设置了这个setJavaScriptEnabled(true); public boolean shouldOverrideUrlLoading(WebView view, String url),在