不知道各位童鞋们在开发的过程中有没有感兴趣过ListView是如何实现的呢?其实本身ListView的父类AbsListView才是关键,但是如果大家看过源码的话,会发现AbsListView将近7000多行代码,是不是头大啊,呵呵,没事,下面咱们就一起来看看吧。

我们先从类中的常量开始分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static final int TRANSCRIPT_MODE_DISABLED = 0;
public static final int TRANSCRIPT_MODE_NORMAL = 1;
public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2;
static final int TOUCH_MODE_REST = -1;
static final int TOUCH_MODE_DOWN = 0;
static final int TOUCH_MODE_TAP = 1;
static final int TOUCH_MODE_DONE_WAITING = 2;
static final int TOUCH_MODE_SCROLL = 3;
static final int TOUCH_MODE_FLING = 4;
static final int TOUCH_MODE_OVERSCROLL = 5;
static final int TOUCH_MODE_OVERFLING = 6;
static final int LAYOUT_NORMAL = 0;
static final int LAYOUT_FORCE_TOP = 1;
static final int LAYOUT_SET_SELECTION = 2;
static final int LAYOUT_FORCE_BOTTOM = 3;
static final int LAYOUT_SPECIFIC = 4;
static final int LAYOUT_SYNC = 5;
static final int LAYOUT_MOVE_SELECTION = 6;
public static final int CHOICE_MODE_NONE = 0;
public static final int CHOICE_MODE_SINGLE = 1;
public static final int CHOICE_MODE_MULTIPLE = 2;
public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;

上面的含义分别如下:

1、禁止副本模式

2、当数据集合发生变化的通知被接受到,列表将会自动的滚向底部。但条件必须是最后一条数据已经出现在屏幕上

3、列表将会自动的滚动到底部,不论当前的数据是否可见。

4、猜测我们并不是在触摸的手势中间。

5、假设我们接收到一个touch的触摸的事件,我们等待去看到它是否是一个滑动的手势。

6、预测到当前的touch事件是一个tap事件,我们正在等待这是否是一个长按的事件。

7、其余的常量与此类此,在此省略了。

接下来我们来看一一批与视图绘制相关的变量:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Drawable mSelector;
int mSelectorPosition = INVALID_POSITION;
Rect mSelectorRect = new Rect();
final RecycleBin mRecycler = new RecycleBin();
int mSelectionLeftPadding = 0;
int mSelectionTopPadding = 0;
int mSelectionRightPadding = 0;
 
int mSelectionBottomPadding = 0;
Rect mListPadding = new Rect();
int mWidthMeasureSpec = 0;
View mScrollUp;
View mScrollDown;
boolean mCachingStarted;
boolean mCachingActive;
int mMotionPosition;
int mMotionViewOriginalTop;
int mMotionViewNewTop;
 
int mMotionX;
 
int mMotionY;
 
int mTouchMode = TOUCH_MODE_REST;
int mLastY;
 
int mMotionCorrection;
private VelocityTracker mVelocityTracker;
 
private FlingRunnable mFlingRunnable;
AbsPositionScroller mPositionScroller;
 
int mSelectedTop = 0;
 
boolean mStackFromBottom;
boolean mScrollingCacheEnabled;
 
boolean mFastScrollEnabled;
boolean mFastScrollAlwaysVisible;
private OnScrollListener mOnScrollListener;

上面的含义分别如下:

1、用来绘制选中项的图片

2、列表中当前被选中的位置

3、在绘制的时刻定义选中的location与对应的尺寸

4、这个数据被设置,存储未使用的视图,它们将会被重用,在接下来的布局中,避免重用。

5、选中的padding的位置

6、向上滚动的标志与向下滚动的标志的视图

7、当这个视图在滚动的时候,这个标志位被设置为true,预示着绘制缓存的子类在其子类上将会是能够的。

8、获取向下的移动的位置

9、其余的变量的注解省略。

接下来,我们看几个接口的定义

1、OnScrollListener

这个接口定义的是当列表或者是九宫格滚动的时候的回调。

在这个接口中存在下面的几个常量

1
2
3
public static int SCROLL_STATE_IDLE = 0;
public static int SCROLL_STATE_TOUCH_SCROLL = 1;
public static int SCROLL_STATE_FLING = 2;

分别指代的是当前的列表处于静止、手指处于触摸状态的滑动以及手指离开的减速滑动并趋向于静止。

其中接口中还定义了两个函数:

1、onScrollStateChanged

2、onScroll

第一个视图是当视图滚动正准备进行时候的回调

第二个视图是当视图的滚动已经结束的回调

2、SelectionBoundsAdjuster

这个接口的含义是允许当前列表项的顶级视图实现这个接口去修改它的展示的边界区域。

接下来的代码选取几个Api来看一下:

1、setFastScrollerEnabledUiThread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void setFastScrollerEnabledUiThread(boolean enabled) {
        if (mFastScroll != null) {
            mFastScroll.setEnabled(enabled);
        } else if (enabled) {
            mFastScroll = new FastScroller(this, mFastScrollStyle);
            mFastScroll.setEnabled(true);
        }
 
        resolvePadding();
 
        if (mFastScroll != null) {
            mFastScroll.updateLayout();
        }
    }

这个方法的功能是显而易见的,操纵的对象是FastScroller,设置是否支持快速的滑动,然后再进行重新绘制视图。

下面的几个方法是计算滚动区域与展示的效果的方法,我们选取几个来看一下:

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
26
27
28
@Override
   protected int computeVerticalScrollExtent() {
       final int count = getChildCount();
       if (count > 0) {
           if (mSmoothScrollbarEnabled) {
               int extent = count * 100;
 
               View view = getChildAt(0);
               final int top = view.getTop();
               int height = view.getHeight();
               if (height > 0) {
                   extent += (top * 100) / height;
               }
 
               view = getChildAt(count - 1);
               final int bottom = view.getBottom();
               height = view.getHeight();
               if (height > 0) {
                   extent -= ((bottom - getHeight()) * 100) / height;
               }
 
               return extent;
           } else {
               return 1;
           }
       }
       return 0;
   }

这个是计算垂直方向上的滚动的区域。

这个算法我们可以看一下

1、

1
extent += (top * 100) / height;

这里面的100我们可以理解为系统假设单个的列表的选项的高度是100,本着多退少补的原则,不论height是大于100还是小于100, 100 / height,得到的数值可以理解为是缩放因子 scaleFactor, top * scaleFactor 计算得到的是最终需要多加的边距。

结伴旅游,一个免费的交友网站:www.jieberu.com

推推族,免费得门票,游景区:www.tuituizu.com

详细讲解Android中的AbsListView的源码的更多相关文章

  1. 详细讲解Android中的Message的源码

    相信大家对于Android中的Handler是在为熟悉不过了,但是要知道,Handler就其本身而言只是一个壳子,真正在内部起到作用的是Message这个类,对于Message这个类,相信大家也不会陌 ...

  2. android中使用afinal一行源码显示网络图片

    下面代码是关于android中使用afinal一行显示网络图片的代码. public class DemoActivity extends FinalActivity { @Override publ ...

  3. 详细讲解Android的网络通信(HttpUrlConnection和HttpClient)

    前言,Android的网络通信的方式有两种:使用Socket或者HTTP,今天这一篇我们详细讲解使用HTTP实现的网络通信,HTTP又包括两种方式编程方式: (1)HttpUrlConnection: ...

  4. 详细讲解Android对自己的应用代码进行混淆加密防止反编译

    1.查看项目中有没有proguard.cfg. 2.如果没有那就看看这个文件中写的什么吧,看完后将他复制到你的项目中. -optimizationpasses 5 -dontusemixedcasec ...

  5. 第五节:详细讲解Java中的接口与继承

    前言 大家好,给大家带来详细讲解Java中的接口与继承的概述,希望你们喜欢 什么是接口(interface) 接口中的方法都是抽象方法,public权限,全是抽象函数,不能生成对象 interface ...

  6. 第四节:详细讲解Java中的类和面向对象思想

    前言 大家好,给大家带来详细讲解Java中的类和面向对象思想的概述,希望你们喜欢 类和面向对象 在Java中怎样理解对象,创建对象和引用:什么是引用,对于基础学习的同学,要深入了解引用.示例:Stri ...

  7. 第九节:详细讲解Java中的泛型,多线程,网络编程

    前言 大家好,给大家带来详细讲解Java中的泛型,多线程,网络编程的概述,希望你们喜欢 泛型 泛型格式:ArrayList list= new ArrayList(); ArrayList list= ...

  8. 第八节:详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架

    前言 大家好,给大家带来详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架的概述,希望你们喜欢 JAVA 异常 try...catch...finally结构的使用方法 class Tes ...

  9. 第七节:详细讲解Java中的日期,java.util.date

    前言 大家好,给大家带来详细讲解Java中的日期,java.util.date的概述,希望你们喜欢 类Date Java.lang.Object->java.util.Date public c ...

随机推荐

  1. 【Python】我的豆瓣短评爬虫的多线程改写

    对之前我的那个豆瓣的短评的爬虫,进行了一下架构性的改动.尽可能实现了模块的分离.但是总是感觉不完美.暂时也没心情折腾了. 同时也添加了多线程的实现.具体过程见下. 改动 独立出来的部分: MakeOp ...

  2. 使用app.config中的数据对数据库链接信息初始化

    看到别人数据库信息都是在app.config里面设置的,今天来尝试了一下,报了 "System.Configuration.ConfigurationSettings.AppSettings ...

  3. 【转】MySQL查询缓存详解

    [转]MySQL查询缓存详解 转自:https://www.cnblogs.com/Alight/p/3981999.html 相关文章:http://www.zsythink.net/archive ...

  4. RocketMQ高可用集群

    集群支持: RocketMQ天生对集群的支持非常友好 单Master: 优点:除了配置简单没什么优点 缺点:不可靠,该机器重启或宕机,将导致整个服务不可用 多Master: 优点:配置简单,性能最高 ...

  5. pg_receivewal实践

    测试从pg_receivewal的日志中恢复从库为主库: 主从配置async模式,配置pg_receivewal接收日志pg_receivewal -D /dbaas/pg/data/pg_recei ...

  6. IDEA 快捷键 (长期更新)

    自动清除无效 import 和 清除无效 import  ctrl+alt+o    

  7. 如何查看SQL Server某个存储过程的执行历史【转】

    db_name(d.database_id) as DBName, s.name as 存储名称, s.type_desc as 存储类型, d.cached_time as SP添加到缓存的时间, ...

  8. P1056排坐椅

    这是2008普及组真题,是一个提高—的模拟. 仔细读完题便有了思路:累放在i行能隔开wi个,比较排序wi,输出即可.所以在这里遇到了结构体排序的问题与手写cmp的问题.对于两个语法知识掌握得都不好,所 ...

  9. Linux——临界段,信号量,互斥锁,自旋锁,原子操作

    一. linux为什么需要临界段,信号量,互斥锁,自旋锁,原子操作? 1.1. linux内核后期版本是支持多核CPU以及抢占式调度.这里就存在一个并发,竞争状态(简称竟态). 1.2. 竞态条件 发 ...

  10. Tarjan水题系列(3):HNOI2006 潘多拉的魔盒

    题目: 链接 大意: 盒子与盒子之间的关系构成一个有向图 求图上包含节点数最多的路径的节点数 思路: 有向图上求包含节点数最多的路径的节点数 可直接使用tarjan缩点后拓扑dp求得 在此不赘述 此题 ...