PinnedListView分析一
分享一个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分析一的更多相关文章
- PinnedListView分析二
在PinnedListView分析一中还有一些细节在本文做一个补充,主要是view的绘制: 一个view在真正被绘制都是通过canvas来做,在ViewGroup内的z子view,一般再次此之前,还需 ...
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- 火焰图分析openresty性能瓶颈
注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...
- 一起来玩echarts系列(一)------箱线图的分析与绘制
一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...
- 应用工具 .NET Portability Analyzer 分析迁移dotnet core
大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- 查看w3wp进程占用的内存及.NET内存泄露,死锁分析
一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...
- ZIP压缩算法详细分析及解压实例解释
最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
随机推荐
- CentOS 7 安装中文环境
centos升级到7后,系统设置好多和6有了很大的区别,中文支持就有很大的变化. 1.安装中文语言包. yum install kde-l10n-Chinese 2.安装(已经安装的要重新安装)gli ...
- 第一个UG练习
- VS2010如何重置开发环境
在利用VS进行软件开发的过程中,我们时不时要因为各种原因,对VS的开发环境进行变动,对于很多初次接触VS这样一个十分好用方便的编程工具的人来说,更改编程环境成了一个难题,今天我们就来讲解一下,如何更改 ...
- HTML杂记
1.URL uniform resource locator 遵循格式: scheme://host.domain:port/path/filename scheme - 定义因特网服务的类型.最常 ...
- CCShatteredTiles3D
CCSprite* pImgBg = CCSprite::create("1.png"); pImgBg->setPosition(ccp(CCDirector::share ...
- .NET MVC5+ Dapper+扩展+微软Unity依赖注入实例
1.dapper和dapper扩展需要在线安装或者引用DLL即可 使用nuget为项目增加Unity相关的包 2.model类 public class UserInfo { public int I ...
- 解决windows10 里vs2015 附件进程调试提示“此任务要求应用程序有提升的权限”
刚用windows10 ,感觉有些地方别扭.就在是vs2015开发程序的时候,就遇到了个问题. 首先 我是使用adminitrator账号登陆的. 双击vs解决方案,打开iis,然后结合vs2015里 ...
- Linux环境系搭建Git服务器过程全纪录
Last :: from 139.199.180.186 [root@VM_219_131_centos ~]# yum install curl-devel expat-devel gettext- ...
- LeetCode: Binary Tree Maximum Path Sum 解题报告
Binary Tree Maximum Path SumGiven a binary tree, find the maximum path sum. The path may start and e ...
- linux清理Java环境
1.清理Java环境rm -f /usr/bin/javarm -f /etc/alternatives/java rm -f /usr/bin/javacrm -f /etc/alternative ...