不知道各位童鞋们在开发的过程中有没有感兴趣过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. 【Linux开发】【Qt开发】交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别

    一. 什么是ABI和EABI1) ABI: 二进制应用程序接口(Application Binary Interface (ABI) for the ARM Architecture)在计算机中,应用 ...

  2. linux中防止黑客进入单用户模式进行强制修改密码窃取数据

    如何防止别人恶意通过单用户系统破解root密码,进入系统窃取数据? 给grub加密,不让别人通过grub进入单用户. 当前系统:CentOS Linux release 7.6.1810 (Core) ...

  3. spring扩展点之PropertyPlaceholderConfigurer

    原理机制讲解 https://leokongwq.github.io/2016/12/28/spring-PropertyPlaceholderConfigurer.html 使用时多个配置讲解 ht ...

  4. [转帖]Linux shell中2>&1的含义解释 (全网最全,看完就懂)

    Linux shell中2>&1的含义解释 (全网最全,看完就懂) https://blog.csdn.net/zhaominpro/article/details/82630528   ...

  5. 将从model中获得的数据传到js函数中

    刚遇到了一种情况,从controller中获得的model是一个集合,需要将这个集合循环放到标签中,并且需要为这些标签添加点击事件,每个值传入对应的点击事件函数中,由于model中的值是通过${ite ...

  6. java int转Short

    使用short(xx) problemMultipleChoiceDO.setExamCount((short)0);//在数据库中是smallint类型

  7. Vue.nextTick浅析

    Vue.nextTick浅析 Vue的特点之一就是响应式,但数据更新时,DOM并不会立即更新.当我们有一个业务场景,需要在DOM更新之后再执行一段代码时,可以借助nextTick实现.以下是来自官方文 ...

  8. 「POI2010」反对称 Antisymmetry (manacher算法)

    # 2452. 「POI2010」反对称 Antisymmetry [题目描述] 对于一个 $0/1$ 字符串,如果将这个字符串 $0$ 和 $1$ 取反后,再将整个串反过来和原串一样,就称作「反对称 ...

  9. P4290 [HAOI2008]玩具取名

    传送门 $dp$ 设 $f[i][j][k]$ 表示初始为 $k$ 时,能否得到 $[i,j]$ 这一段子串 设 $pd[i][j][k]$ 表示长度为二的字符串 $ij$ 能否由 $k$ 得到 然后 ...

  10. jQuery之样式的类操作

    方法:添加类addClass    .删除类removeClass. 切换类toggleClass <style> div { width: 150px; height: 150px; b ...