
在很多应用中,看到这样的listview:listview滑动过程中分组标题固定在上方,当第二个组滑上来时,第一个组才跟着上滑,下一个组固定,直到该组也滑出上边缘。世上无难事只怕有心人,在github上就有人做出来了,而且效果很好(后来发现安卓自带应用中联系人应用就是这样的,估计github的作者也是仿照着联系人做出来的吧)。
先看截图:
PinnedSectionListView继承自listview,众所周知listview的每个子view都是按顺序跟着滚动的,要实现联系人listview的效果还真的找不到思路。看了PinnedSectionListView之后,感觉要改造一个现有的控件,一般都是通过重绘子view来实现的。ViewGroup(ListView继承自它)重绘子view的方法是dispatchDraw。
看看PinnedSectionListView在dispatchDraw中有那些特别的处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@Override
protected void dispatchDraw(Canvas canvas) {
super
.dispatchDraw(canvas);
if
(mPinnedSection !=
null
) {
// prepare variables
int pLeft = getListPaddingLeft();
int pTop = getListPaddingTop();
View view = mPinnedSection.view;
// draw child
canvas.save();
int clipHeight = view.getHeight() +
(mShadowDrawable ==
null
? 0 : Math.min(mShadowHeight, mSectionsDistanceY));
canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight);
canvas.translate(pLeft, pTop + mTranslateY);
drawChild(canvas, mPinnedSection.view, getDrawingTime());
if
(mShadowDrawable !=
null
&& mSectionsDistanceY > 0) {
mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),
mPinnedSection.view.getBottom(),
mPinnedSection.view.getRight(),
mPinnedSection.view.getBottom() + mShadowHeight);
mShadowDrawable.draw(canvas);
}
canvas.restore();
}
}
|
关键在于canvas.translate(pLeft, pTop + mTranslateY);
意思是在绘制mPinnedSection
的时候,listview滑动了多长的距离,就将canvas移动多少的距离,使mPinnedSection
始终在可见的范围内固定不变。
使用方法:
1.在xml布局文件中将ListView替换成PinnedSectionListView
1
2
3
4
5
|
<com.hb.views.PinnedSectionListView
android:id=
"@android:id/list"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
|
2.让你的ListAdapter继承PinnedSectionListAdapter
接口,最简单的做法是只增加isItemViewTypePinned
方法,该方法必须在item为pinned的情况下返回true。
1
2
3
4
5
6
7
8
9
|
// Our adapter class implements 'PinnedSectionListAdapter' interface
class MyPinnedSectionListAdapter extends BaseAdapter implements PinnedSectionListAdapter {
...
// We implement this method to return 'true' for all view types we want to pin
@Override
public boolean isItemViewTypePinned(int viewType) {
return
viewType == <type to be pinned>;
}
}
|
项目地址:https://github.com/beworker/pinned-section-listview
最后推荐一个demo:http://blog.youkuaiyun.com/anddroid_lanyan/article/details/41895631

版权声明:本文为博主原创文章,未经博主允许不得转载。
网上开源项目:https://github.com/beworker/pinned-section-listview,该项目用的是ArrayAdapter()..不太适合我,稍作修改,仿的微信界面
PinnedSectionListView修改了一行代码,不然会报错,代码如下
void createPinnedShadow(int position) {}》》

版权声明:本文为Zhang Phil原创文章,欢迎转载!转载请注明出处:http://blog.youkuaiyun.com/zhangphil
Android PinnedSectionListView是一个良好的第三方开源悬停分组ListView,其在github上的项目主页是:https://github.com/beworker/pinned-section-listview ,在涉及到一些联系人分组,好友分组等需要对ListView进行分组的情况下,使用起来效果不错。
但是作为开源项目,本身也在不停的迭代和完善中,最近(截止2015年11月26日)发现PinnedSectionListView在一些Android SDK版本中运行时候异常崩溃报错,如图:
报错的关键内容是:
错误内容提示在PinnedSectionListView.Java的202行出现错误,这是PinnedSectionListView.java源代码中的原始内容:
如图:
经由研究发现,此原因是在调用Android系统的generateDefaultLayoutParams()方法时候,发生异常,致使代码运行获得的结果layoutParams不正常,进而导致PinnedSectionListView崩溃。
解决方案:
自己动手重写Android系统的generateDefaultLayoutParams()方法,返回自己定制的LayoutParams值。
具体实现:
在PinnedSectionListView.java中增加自己重写的generateDefaultLayoutParams()方法: