Android-ScrollView

本贴最后更新于 3578 天前,其中的信息可能已经东海扬尘

项目中有用到一个类似于日期时间的滑动选择控件,然而感觉 android 自带的 DataPicker 与 app 的整体风格不太一样,于是想着自己写一个超级简洁美丽大方的控件出来。

本来想到滑动选择,就想到了 scrollview,然后在网上搜了一下,谁想到网上资料全都是一样的。。一点营养都没有,虽然最后由于 API 版本的原因没有采用 scrollview 的方式,但是中间对其研究了一下,特此分享。


ScrollView基本用法介绍

ScrollView的主要用处是,当你在一个界面上显示的内容超过了display大小的时候,用scrollview滑动显示,比如大众点评一些app的主页面。这里还要提一下ScrollView里用到了很多次Nest,这是为什么?

因为Nest是嵌套的意思,个人认为ScrollView的设计初衷是嵌套在整个Display中,如果你创建一个带ActionBar的Activity,就会发现,向下滑动ScrollView,ActionBar会自动消失,向上滑动则会出现。
用法:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_gravity="center"
    android:layout_width="100dp"
    android:layout_height="80dp" tools:context=".MainActivity">
    <LinearLayout
        android:id="@+id/scrollview"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/text"
            android:text="2010"
            android:textSize="30dp"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/text23"
            android:text="2010"
            android:textSize="30dp"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</ScrollView>

这里要注意,ScrollView只能有一个childview,一般用一个LinearLayout来实现,在LinearLayout中添加其他控件。


ScrollView初始化

ScrollView继承FrameLayout,所以等级和LinearLayout这些是一样的,初始化也大同小异,无非就是传递一些attr和style的值,这里有几个变量介绍一下,在initScrollView()中


       
 mTouchSlop = configuration.getScaledTouchSlop();
        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
        mOverscrollDistance = configuration.getScaledOverscrollDistance();
        mOverflingDistance = configuration.getScaledOverflingDistance();


mTouchSlop是触摸溢出极限值了,这个在后面onTouch里会提到
Velocity是速率的意思,fling是掷的意思,我理解为手指在屏幕上的快速滑动
Touch行为

和其他View的Touch一样,先传给onTouchEvent之前,传递给onInterceptTouchEvent函数,首先*ACTION.DOWN*行为,


       
 if (actionMasked == MotionEvent.ACTION_DOWN) {
            mNestedYOffset = 0;
        }
        vtev.offsetLocation(0, mNestedYOffset);


记录mNestedYOffset,Y方向上的offset


case MotionEvent.ACTION_DOWN: {
                if (getChildCount() == 0) {
                    return false;
                }
                if ((mIsBeingDragged = !mScroller.isFinished())) {
                    final ViewParent parent = getParent();
                    if (parent != null) {
                        parent.requestDisallowInterceptTouchEvent(true);
                    }
                }
/* * If being flinged and user touches, stop the fling. isFinished * will be false if being flinged. */ if (!mScroller.isFinished()) { mScroller.abortAnimation(); if (mFlingStrictSpan != null) { mFlingStrictSpan.finish(); mFlingStrictSpan = null; } } // Remember where the motion event started mLastMotionY = (int) ev.getY(); mActivePointerId = ev.getPointerId(0); startNestedScroll(SCROLL_AXIS_VERTICAL); break;</pre>


这里会检测到ScrollView是否正在被拉动,如果没有被拉动,就停止动画
同时得到mLastMotionY,就是手指按下的位置
还有mActivePointerId,这里的Pointer可以当做手指产生的trace代号,如果有multi-touch,就会有多个pointer,在这里不是重点,不细说。


接下来是*ACTION_MOVE*


      
   final int y = (int) ev.getY(activePointerIndex);
         int deltaY = mLastMotionY - y;
         if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
                 deltaY -= mScrollConsumed[1];
                 vtev.offsetLocation(0, mScrollOffset[1]);
                 mNestedYOffset += mScrollOffset[1];
         }


deltaY大家都能看懂,重点是dispatchNestedPreScroll(0,deltaY,mScrollConsumed,mScrollOffset)这个函数,先说一下后两个参数的意义,mScrollConsumed就是Parent消耗的滑动的部分(其实我不太明白为什么会有这个参数,是为了让滑动不要太敏感吗?但是我们可以从这个参数知道,我们最终ScrollView滑动的距离是由parent消耗的一部分和真正的滑动的一部分所组成的),第4个参数就是scrollview已经产生的offset了。这个函数名字叫做PreScroll,我们也可以知道这是预滑动,也就是childview还没有开始滑动前做的动作。
在这个函数里做了什么呢?
其实调用了mNestedScrollingParent.onNestedPreScroll,也就是parent的prescroll,然后产生一个consumed和offset传递回来。
返回之后,我们可以看到deltaY-mScrollConsumed[1]得到的就是真正的childview所需要滑动的deltaY了,然后记录下来。


其实后面的代码也和上面类似,就不做多解释了。看完这个,你应该对ScrollView有了一个大致的了解,之后运用起来相信会更加的娴熟。


千万要记住一点,不要在ScrollView中嵌套上已经具有Scroll功能的控件里,比如ListView,比如装载不下的TextView。





  • ScrollView
    3 引用
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    336 引用 • 324 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    345 引用 • 753 回帖
  • Access
    1 引用 • 3 回帖 • 3 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    180 引用 • 1279 回帖
  • 博客

    记录并分享人生的经历。

    273 引用 • 2388 回帖
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    77 引用 • 37 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 414 关注
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    211 引用 • 358 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖
  • V2Ray
    1 引用 • 15 回帖 • 1 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    315 引用 • 547 回帖 • 1 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 13 关注
  • RemNote
    2 引用 • 16 回帖 • 20 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    43 引用 • 44 回帖
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    167 引用 • 597 回帖
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    59 引用 • 25 回帖 • 2 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    125 引用 • 74 回帖 • 3 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    45 引用 • 114 回帖 • 171 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 271 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 707 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 3 关注
  • 笔记

    好记性不如烂笔头。

    310 引用 • 794 回帖
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    198 引用 • 543 回帖
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    693 引用 • 537 回帖
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 363 关注
  • OpenCV
    15 引用 • 36 回帖 • 8 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 402 关注