Android-ScrollView

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

项目中有用到一个类似于日期时间的滑动选择控件,然而感觉 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 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    335 引用 • 324 回帖 • 4 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    730 引用 • 1280 回帖 • 5 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    494 引用 • 930 回帖
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 375 关注
  • danl
    164 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 676 关注
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 67 回帖 • 446 关注
  • abitmean

    有点意思就行了

    36 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    21 引用 • 245 回帖 • 228 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 2 关注
  • Git

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

    211 引用 • 358 回帖 • 1 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 740 关注
  • 笔记

    好记性不如烂笔头。

    310 引用 • 794 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 546 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 4 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 1 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 177 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    29 引用 • 202 回帖 • 31 关注
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1708 回帖
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    24 引用 • 241 回帖
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 3 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    184 引用 • 1018 回帖 • 2 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    952 引用 • 944 回帖
  • NetBeans

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

    78 引用 • 102 回帖 • 705 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 17 关注
  • WordPress

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

    66 引用 • 114 回帖 • 190 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    170 引用 • 1529 回帖