分享一个Android控件,PinnedHeaderListView , 大致是像图钉一样,能够固定显示一个头部在ListView的顶部,类似于Android原版通讯录中联系人按照字母分组排列, 这个东西其实出来很久了,今天仔细阅读了源码,再次做一个分享。

效果预览

下面的图左边是预览的效果,右边则是项目涉及的重要类。

原理概述   

  • 为了便于分析,我们先做一些命名的约定。这个List继承自ListView,灰色半透明item暂且称其为section view,而其他的白色条目暂称为item view,当section view滑动至顶部后将停留在顶部,而白色的item view可以继续上划消失,这里固定后的section view 我们暂时称其为current header view,注意它实际上不存在于ListView内部,而是实时可变的画在顶部的view。
  • 通过滑动事件监听,在onScroll()内设置current header view的内容和位置的偏移量,在每次滑动事件的结尾触发lisview进行重绘,这时再dispatchDraw()中通过canvas来绘制视图。
  • 与之配套的adapter则实现一些具体的view的实例化操作和区分不同的view,比如section view和item view,以及这两种view各自的view type处理等等。

实现分析

我们已经知道他的实现机制,现在先来具体分析一下的内部实现,涉及到的类可以在上面的预览图中看到,主要是PinnedHeaderListView 和SectionedBaseAdapter以及相关接口定义和实现。

  • PinnedHeaderListView

下面是它定义的一些重要成员,具体作用我已经在后面加了注释, 其中的mCurrentHeader即为current header view。

private View mCurrentHeader;// pinned top header view

private int mCurrentHeaderViewType = 0;

private float mHeaderOffset;// offset for pinned header view

private boolean mShouldPin = true;//default to enable pinned header view

在PinnedHeaderListView内部他继承了ListView并实现了OnScrollListener接口,现在我们先分析onScroll里面所做的事情,大致可以分为四块:

1.外部on scroll的的触发,

首先是重载了ListView得setOnScrollListener()方法,通过成员变量mOnScrollListener来引用外部设置的listener,然后再已经实现的OnScrollListener接口中调用mOnScrollListener,

这样一来我们任然可以在空间外部设置setOnScrollListener做其他的事情.

  2. 处理section view尚未接触顶部的状态

如果listview是空的或者我们通过setPinHeaders()使得listview不要pinned效果或则listview有设置header并且滑动时header还未完全出屏幕外,那么走下面的段代码,把current header view和他的offset置空,然后遍历所有子view设置为visible的状态,注意这一步是是必须的,因为在其他地方我们有可能会把子view设为invisible,而这个地方就是在设置pinned current header view的时候。

3. 复用或实例化pinned current header view

我已经在代码中加了注释,首先是计算出listview 原始header之外的item的索引起始位置,此时header如果存在,那么已经划出屏幕了,也就是当前第一个显示的位置减去header个数;根据这个item的position来获取对应的section view的position和view type,具体的代码实现在SectionBaseAdapter里面。接着是获取current header view的实例,根据view type和和当前的位置position是否变化,可能是复用的也可能是全新创建的

4. 遍历所有的section view设置visibility

现在从屏幕上可见的子section view开始遍历,计算出section view的顶部Y坐标,和pinned current header view的高度作比较,当section view向上滑动到开始与pinned current header view的区域相交时,我们计算出交叉的高度作为current header view的Y轴偏移量,继续向上滑动,当section view的顶部Y坐标小于0,也就是开始要划出屏幕时我们设置它为invisible,这样做的目的在于造成错觉,好像section view被定在了list view得顶部,实际上如果这里我们不把他设为invisible那么在demo运行时你将更清晰的发现原来向上滑动的section view其实一直在向上滑动。


最后我们需要调用 invalidate();来重绘界面,这样我们刚才更新的current header view 的偏移量就会在绘制的时候生效。

分析到这里我们对PinnedHeaderListView已经有了更深刻的理解,如果你发现思路有点跟不上下面的这张简略的流程图可能会有所帮助。

对与之配套的Adapter我将在下一篇文章在做分析…..

PinnedListView分析一的更多相关文章

  1. PinnedListView分析二

    在PinnedListView分析一中还有一些细节在本文做一个补充,主要是view的绘制: 一个view在真正被绘制都是通过canvas来做,在ViewGroup内的z子view,一般再次此之前,还需 ...

  2. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  3. 火焰图分析openresty性能瓶颈

    注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...

  4. 一起来玩echarts系列(一)------箱线图的分析与绘制

    一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...

  5. 应用工具 .NET Portability Analyzer 分析迁移dotnet core

    大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...

  6. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  7. 查看w3wp进程占用的内存及.NET内存泄露,死锁分析

    一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...

  8. ZIP压缩算法详细分析及解压实例解释

    最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...

  9. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

随机推荐

  1. java集群优化——ORM框架查询优化原理

    众所周知,当下的流行的企业级架构中,ORM一直是最基础的部分,在架构设计的底层.对逻辑层提供面向对象的操作支持,而事实总是和我们预想的有所偏差,ORM在提供了较好的操作体验时,也流失了一部分原生SQL ...

  2. JAVA与C++,C与C++的差别

    首先来分析JAVA与C++的差别: JAVA是纯面向对象的语言,而C++是基于面向对象过程的语言. JAVA有着垃圾回收机制.它的语法是C++的子集,即JAVA有的C++都有.而C++有的JAVA不全 ...

  3. DCOS :私有云的物理基础架构管理引擎

    https://cloud.tencent.com/developer/article/1005598 一.引言 云计算经过多年的发展,逐渐从概念到渐为人认知.到接受.到现在全行业拥抱上云,云的客户也 ...

  4. 关于CentOS 6下Hadoop占用系统态CPU高的处理办法【转】

    一次不经意发现Hadoop的系统态CPU使用率很高,然后百度一下居然是个已知问题. RHEL6优化了内存申请的效率,而且在某些场景下对KVM的性能有明显提升:http://www.Linux-kvm. ...

  5. 在XSLT中输出内容带有CDATA的XML节点

    http://www.cnblogs.com/jaxu/archive/2013/03/13/2956904.html **************************************** ...

  6. poj1077(康托展开+bfs+记忆路径)

    题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如: 1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案.可以右移r,左移l,上移u,下移dx 4 6 4 5 67 ...

  7. 针对后台TCP服务F5健康检查配置

    1.TCP-HALF-OPEN方式 TCP-HALF-OPEN的探测方式,实际是F5每隔一个固定的时间,发送一个SYN包给资源池pool中的一个member,等待服务器返回SYN_ACK,在收到SYN ...

  8. 本质矩阵E求解及运动状态恢复

    为了获取本质矩阵,首先计算基础矩阵F.根据本质矩阵E,即可恢复得到运动的状态R和T. 由可以根据匹配点得到F,然后根据和相机内参,即可得到本质矩阵E.进而根据: 注意:根据摄像机模型t=-RT,恢复运 ...

  9. MAC层作用

    对于无线传感网 MAC,顾名思义,就是介质访问控制,是用来控制无线介质的访问的,由于无线传输是共享空中资源的,必然存在多个无线传感器节点对传输介质的争用,MAC层协议就是用来解决这个问题的,包括冲突的 ...

  10. kafka demo

    public static void main(String[] args) { Properties props = new Properties(); props.put("bootst ...