NestedScrollVew实现原理分析

NestedScrollView 是 Android 中的一个特殊滚动视图,它继承自 ScrollView,但添加了对嵌套滚动(nested scrolling)的支持。这使得 NestedScrollView 可以与其它支持嵌套滚动的视图(如 RecyclerView)协同工作,从而实现更复杂的滚动效果。

下面我们将结合源码来分析 NestedScrollView 的实现原理。

1. NestedScrollView 类定义

NestedScrollView 继承自 ScrollView,因此它也只接受一个直接子视图。与 ScrollView 不同的是,它支持嵌套滚动,这意味着它可以在内部滚动时允许其子视图也进行滚动。

1public class NestedScrollView extends ScrollView implements NestedScrollingParent, NestedScrollingChild {
2
3    // ...
4
5    // 构造函数
6    public NestedScrollView(Context context) {
7        super(context);
8        initScrollView();
9    }
10
11    public NestedScrollView(Context context, AttributeSet attrs) {
12        super(context, attrs);
13        initScrollView();
14    }
15
16    public NestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
17        super(context, attrs, defStyleAttr);
18        initScrollView();
19    }
20
21    private void initScrollView() {
22        // 初始化操作
23        setFillViewport(true);  // 填充整个视口
24        setFocusable(true);     // 可聚焦
25        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);  // 子视图优先获得焦点
26    }
27
28    // 其他方法...
29}

2. 测量过程(onMeasure)

NestedScrollView 的测量过程与 ScrollView 类似,但是它还需要考虑嵌套滚动的情况。

1@Override
2protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
4
5    // 如果有嵌套滚动的子视图,则需要考虑子视图的滚动情况
6    // 如果子视图是嵌套滚动的,那么需要在测量时考虑到子视图的滚动距离
7    if (hasNestedScrollingChild()) {
8        final View child = getChildAt(0);
9        final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
10                child.getMeasuredHeight() + getScrollY(), MeasureSpec.EXACTLY);
11        child.measure(getChildMeasureSpec(widthMeasureSpec,
12                getPaddingLeft() + getPaddingRight(), child.getLayoutParams().width),
13                childHeightMeasureSpec);
14    }
15}

3. 布局过程(onLayout)

布局过程与 ScrollView 相似,但需要考虑嵌套滚动的情况。

1@Override
2protected void onLayout(boolean changed, int l, int t, int r, int b) {
3    final int width = r - l;
4    final int height = b - t;
5    final int paddingLeft = getPaddingLeft();
6    final int paddingTop = getPaddingTop();
7    final int paddingRight = getPaddingRight();
8    final int paddingBottom = getPaddingBottom();
9
10    final int childWidth = width - paddingLeft - paddingRight;
11    final int childHeight = height - paddingTop - paddingBottom;
12
13    final View child = getChildAt(0);
14    if (child != null) {
15        final int childLeft = paddingLeft;
16        final int childTop = paddingTop;
17        child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());
18    }
19}

4. 滚动处理

NestedScrollView 重写了 onTouchEvent 方法来处理触摸事件,并实现滚动功能。它还实现了 NestedScrollingParentNestedScrollingChild 接口中的方法。

1@Override
2public boolean onTouchEvent(MotionEvent ev) {
3    // ...
4    switch (ev.getActionMasked()) {
5        case MotionEvent.ACTION_DOWN:
6            // ...
7            break;
8        case MotionEvent.ACTION_MOVE:
9            // ...
10            break;
11        case MotionEvent.ACTION_UP:
12            // ...
13            break;
14        case MotionEvent.ACTION_CANCEL:
15            // ...
16            break;
17    }
18    return true;
19}

5. 嵌套滚动接口实现

NestedScrollView 实现了 NestedScrollingParentNestedScrollingChild 接口,以便支持嵌套滚动。

1@Override
2public boolean startNestedScroll(int axes) {
3    // ...
4    return true;
5}
6
7@Override
8public void stopNestedScroll() {
9    // ...
10}
11
12@Override
13public boolean hasNestedScrollingParent() {
14    // ...
15    return false;
16}
17
18@Override
19public void dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
20    // ...
21}
22
23@Override
24public void dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
25    // ...
26}
27
28@Override
29public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
30    // ...
31    return false;
32}
33
34@Override
35public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
36    // ...
37    return false;
38}

6. 回调方法

NestedScrollView 提供了 OnScrollChangeListener 接口,允许开发者监听滚动事件。

1public interface OnScrollChangeListener {
2    void onScrollChange(NestedScrollView who, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
3}

7. 平滑滚动

NestedScrollView 使用 AutoScrollHelper 类来实现平滑滚动动画。

1public void smoothScrollTo(int destX, int destY) {
2    AutoScrollHelper.getInstance(this).ensureTarget(this);
3    AutoScrollHelper.getInstance(this).startAnimation(destX, destY);
4}

总结

NestedScrollView 的实现原理与 ScrollView 类似,但是它增加了对嵌套滚动的支持。这使得它可以更好地与其他支持嵌套滚动的视图协同工作。通过重写 onMeasureonLayout 方法,NestedScrollView 确保子视图正确地显示在屏幕上,并且可以通过处理触摸事件来响应用户的滚动操作。此外,它还实现了 NestedScrollingParentNestedScrollingChild 接口,以支持嵌套滚动场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/49755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从头开始微调Llama 3.1模型

在今天的科技专栏中,我们将深入探讨如何微调Llama 3.1模型,以使其更好地适应您的特定领域数据。微调大型语言模型(如Llama)的主要目的是为了在特定领域的数据上表现更好,从而生成更符合您需求的输出。以下是我们将要介…

链表的中间结点 - 力扣(LeetCode)C语言

876. 链表的中间结点 - 力扣(LeetCode)( 点击前面链接即可查看题目) /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* middleNode(struct ListNode* head) {struct Lis…

如何实现一个大模型在回答问题时同时提供相关内容链接

通义生成 为了让大模型在回答问题时能够提供相关内容链接,通常采用的方法是结合检索增强生成(Retrieval-Augmented Generation, RAG)的技术。这种方法可以让大模型在生成答案的同时,从外部知识源中检索相关信息,并将这…

SpringBoot知识笔记

一、基本概念 1.1 特性 起步依赖 自动配置 其它特性:内嵌的Tomcat、Jetty(无需部署WAR文件),外部配置,不需要XML配置(properties/yml)。 1.2 配置文件 SpringBoot提供了多种属性配置方式 //application.properties server.port=9090 server.servlet.context-path…

状态模式与订单状态机的实现

状态模式 状态模式(State Design Pattern)是一种行为设计模式,用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中,使得对象在状态变化时不会影响到其他代码,提升了代码的灵活性和可维…

Python爬虫知识体系-----Urllib库的使用

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新:https://blog.csdn.net/grd_java/article/details/140574349 文章目录 1. 基本使用2. 请求对象的定制3. 编解码1. get请求方式:urllib.parse.quote()2. ur…

邦布带你从零开始实现图书管理系统(java版)

今天我们来从零开始实现图书管理系统。 图书管理系统 来看我们的具体的实现,上述视频。 我们首先来实现框架,我们要实现图书管理系统,首先要搭框架。 我们首先定义一个书包,在书包中定义一个书类和一个书架类,再定义…

数据库之常用函数

目录 一、数值函数 1.求绝对值函数 2.求余函数 3.用于获取整数的函数 4.获取随机数的函数 5.四舍五入函数 6.截取小数函数 二、字符串函数 1.返回字符串长度和字符串中字符个数的函数 2.合并字符串的函数 3.替换字符串的函数 4.字母大小写转换函数 5.获取指定长度…

Webpack、Vite区别知多少?

前端的项目打包,我们常用的构建工具有Webpack和Vite,那么Webpack和Vite是两种不同的前端构建工具,那么你们又是否了解它们的区别呢?我们在做项目时要如何选择呢? 一、工具定义 1、Webpack:是一个强大的静态模块打包工…

用Java手写jvm之实现查找class

写在前面 完成类加载器加载class的三阶段,加载,解析,初始化中的加载😀😀😀 源码 。 jvm想要运行class,是根据类全限定名称来从特定的位置基于类加载器来查找的,分别如下:…

go语言与UPX

源自:压缩工具之upx_51CTO博客_za压缩工具 下面是直接copy的: 在golang项目中, 最终运行的是打包好的二进制文件,如何才能让这个文件尽可能的小呢? 1.编译阶段的参数处理 go build使用的是静态编译,会将程序的依赖一起打包,这…

【SQL 新手教程 2/20】关系模型 -- 主键

💗 关系数据库建立在关系模型上⭐ 关系模型本质上就是若干个存储数据的二维表 记录 (Record): 表的每一行称为记录(Record),记录是一个逻辑意义上的数据 字段 (Column):表的每一列称为字段(Colu…

【算法】二进制常用操作

二进制常用操作 求n的二进制中第k位数字: n > > k & 1 n>>k\& 1 n>>k&1​ lowbit(x)的用法:返回x中最后一个1, l o w b i t ( x ) x & ( − x ) lowbit(x)x\&(-x) lowbit(x)x&(−x)​ 输入一个 32 位整数&a…

java如何同时继承接口和抽象类

java中要同时继承接口和抽象,需要用到的语句是 class 类名 extends 抽象类名 implements 接口 示例代码如下 interface Animal02{public String Name"牧羊犬";public void shout();public void info(); } abstract class Action01{public abstract voi…

解锁Vue的潜力:封装递归组件的经验之谈(网站导航层架嵌套)

最近在使用BootstrapVue写一个网站(我也不知道为啥要用这个😂),使用到了NavBarDropDown等一些组件的组合,可以自动创建一个响应式的效果,还不错。But…,这个DropDown只支持到二级。有人2019年就在Github上提了issue- dropdown submenu并且作者…

WebKit的CSS Aspect Ratio Box:重塑响应式设计

WebKit的CSS Aspect Ratio Box:重塑响应式设计 在响应式网页设计中,保持元素的宽高比是一个常见需求。幸运的是,CSS提供了一个名为aspect-ratio的属性,它允许开发者为元素定义一个理想的宽高比。在WebKit中,这个属性得…

吴恩达的TranslationAgent学习

TranslationAgent构成 整个[TranslationAgent (github.com)]在流程上分为短文本的一次性翻译和长文本的分chunk翻译(按照Token进行划分)。 但是不论长文本翻译还是短文本翻译,总体流程遵循执行、纠正再执行的逻辑循环实现。 这种按照自省思路…

数据库DDL | 增 删 改 操作 | 对数据库数据表

DDL建库建表(操作数据库/表)⭐️⭐️⭐️ 数据库 创建库 //create database 库名 create database xiaozhao2;查看库 //查看所有的库 show databases;删除库(危险操作) //drop database 库名 drop database xiaozhao2;使用库\切换库 //use 库名 use xiaozhao2;查看库数据…

【数字IC/FPGA】使用Verdi对比两个波形

步骤一: 使用verdi打开第一个波形 bsub verdi -ssf 1.fsdb添加需要观察的信号,如下图所示: 步骤二: 新建容器,依次点击Window --> Dock to --> New Container Window。 然后输入容器的名字,如下图所…

SQL数据库:通过在视频监控平台服务器上直接使用SQL存储过程,在海量记录中查询特定时间段内-某个摄像头的所有视频片段

目录 一、背景 1、存储过程 2、视频监控系统 二、需求和数据表 1、具体要求 2、数据表 3、部分数据 三、实现 1、目标 2、创建存储过程 (1)存储过程代码 (2)创建成功 3、存储过程的解释 4、SQL命令调用方式 5、调用…