[Android学习整理]之从源码分析mScrollX,scrollTo(),smoothScrollTo

前言

a.度娘一下什么都知道了,整理这些东西有什么用?还费时费力的! 如何才能完全掌握一个知识?当你能把它讲清楚的时候,你才算掌握了他,所以这也是我整理这些知识点最大的原因。

想完全把mScrollX和mScrollY,scrollTo()和scrollBy(),smoothScrollTo和smoothScrollBy弄明白并不容易,但查阅他们的源代码基本就能明白个大概,这篇文章就是从源码分析他们究竟有什么作用和区别,读懂了基本就会用!


地址

我的CSDN主页:http://blog.csdn.net/xiangyong1521 文章地址:http://blog.csdn.net/xiangyong1521/article/details/77826942

目录

  • mScrollX和mScrollY
  • scrollTo()和scrollBy()
  • smoothScrollBy和smoothScrollTo
  • view和viewgroup

一.mScrollX和mScrollY

/**
     * The offset, in pixels, by which the content of this view is scrolled
     * horizontally.
     * {@hide}
     */
    @ViewDebug.ExportedProperty(category = "scrolling")
    protected int mScrollX;
    /**
     * The offset, in pixels, by which the content of this view is scrolled
     * vertically.
     * {@hide}
     */
    @ViewDebug.ExportedProperty(category = "scrolling")
    protected int mScrollY;


     /**
     * Return the scrolled left position of this view. This is the left edge of
     * the displayed part of your view. You do not need to draw any pixels
     * farther left, since those are outside of the frame of your view on
     * screen.
     *
     * @return The left edge of the displayed part of your view, in pixels.
     */
    public final int getScrollX() {
        return mScrollX;
    }

    /**
     * Return the scrolled top position of this view. This is the top edge of
     * the displayed part of your view. You do not need to draw any pixels above
     * it, since those are outside of the frame of your view on screen.
     *
     * @return The top edge of the displayed part of your view, in pixels.
     */
    public final int getScrollY() {
        return mScrollY;
    }

直接翻译就可以得知

mScrollX:表示离视图起始位置的x水平方向的偏移量

mScrollY:表示离视图起始位置的y垂直方向的偏移量

通过getScrollX() 和getScrollY()方法获这兄弟俩。 注意:mScrollX和mScrollY指的并不是坐标,而是偏移量。


二.scrollTo()和scrollBy()

<span style="font-family:SimSun;font-size:14px;"> /** 
     * Set the scrolled position of your view. This will cause a call to 
     * {@link #onScrollChanged(int, int, int, int)} and the view will be 
     * invalidated. 
     * @param x the x position to scroll to 
     * @param y the y position to scroll to 
     */  
    public void scrollTo(int x, int y) {  
        if (mScrollX != x || mScrollY != y) {  
            int oldX = mScrollX;  
            int oldY = mScrollY;  
            mScrollX = x;  
            mScrollY = y;  
            invalidateParentCaches();  
            onScrollChanged(mScrollX, mScrollY, oldX, oldY);  
            if (!awakenScrollBars()) {  
                postInvalidateOnAnimation();  
            }  
        }  
    }  

    /** 
     * Move the scrolled position of your view. This will cause a call to 
     * {@link #onScrollChanged(int, int, int, int)} and the view will be 
     * invalidated. 
     * @param x the amount of pixels to scroll by horizontally 
     * @param y the amount of pixels to scroll by vertically 
     */  
    public void scrollBy(int x, int y) {  
        scrollTo(mScrollX + x, mScrollY + y);  
    }</span>

源码可以看出,scrollTo 和 scrollBy区别,其实2者的效果是一样的,只是过程不同而已。

scrollTo(int x,int y):

如果偏移位置发生了改变,就会给mScrollX和mScrollY赋新值,改变当前位置。 注意:x,y代表的不是坐标点,而是偏移量。 例如: 我要移动view到坐标点(100,100),那么我的偏移量就是(0,,0) - (100,100) = (-100 ,-100) ,我就要执行view.scrollTo(-100,-100),达到这个效果。

scrollBy(int x,int y):

从源码中看出,它实际上是调用了scrollTo(mScrollX + x, mScrollY + y); mScrollX + x和mScrollY + y,即表示在原先偏移的基础上在发生偏移,通俗的说就是相对我们当前位置偏移。 根据父类VIEW里面移动,如果移动到了超出的地方,就不会显示。


三.smoothScrollTo和smoothScrollBy

ScrollView.smoothScrollBy和smoothScrollTo的源码

/**
     * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
     *
     * @param dx the number of pixels to scroll by on the X axis
     * @param dy the number of pixels to scroll by on the Y axis
     */
    public final void smoothScrollBy(int dx, int dy) {
        if (getChildCount() == 0) {
            // Nothing to do.
            return;
        }
        long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
        if (duration > ANIMATED_SCROLL_GAP) {
            final int height = getHeight() - mPaddingBottom - mPaddingTop;  //获取部件高度
            final int bottom = getChildAt(0).getHeight();   //获取当前能看到的item高度
            final int maxY = Math.max(0, bottom - height);   
            final int scrollY = mScrollY;
            dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY;

            mScroller.startScroll(mScrollX, scrollY, 0, dy);
            postInvalidateOnAnimation();
        } else {
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
                if (mFlingStrictSpan != null) {
                    mFlingStrictSpan.finish();
                    mFlingStrictSpan = null;
                }
            }
            scrollBy(dx, dy);
        }
        mLastScroll = AnimationUtils.currentAnimationTimeMillis();
    }

    /**
     * Like {@link #scrollTo}, but scroll smoothly instead of immediately.
     *
     * @param x the position where to scroll on the X axis
     * @param y the position where to scroll on the Y axis
     */
    public final void smoothScrollTo(int x, int y) {
        smoothScrollBy(x - mScrollX, y - mScrollY);
    }

源码可以看出,是ScrollBy和ScrollTo增加滚动动画的升级方案;

moothScrollBy(int dx, int dy) :

dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY;为方法的核心,比较绕,大致为计算当前滑动状态下可划动距离;

if(duration > ANIMATEDSCROLLGAP) 这句是判断当前是否在滚动,当还在滚动状态下,执行mScroller.startScroll(mScrollX, scrollY, 0, dy);当不在滚动,就立马打断。

smoothScrollTo(int x, int y):

从源码中看出,它实际上是调用了smoothScrollBy(x - mScrollX, y - mScrollY);方法 根据x,y的值来计算剩余可滚动的位移量;


四.view和viewgroup

最后讲讲view和viewgroup这俩,完全吃透有点难,通俗讲,Android的UI界面都是由View和ViewGroup及其派生类组合而成的,View是所有UI组件的基类,而ViewGroup是容纳这些组件的容器; View类是ViewGroup的父类,ViewGroup具有View的所有特性,ViewGroup主要用来充当View的容器,将其中的View作为自己孩子,并对其进行管理,当然孩子也可以是ViewGroup类型。

View派生出的直接子类有:AnalogClock,ImageView,KeyboardView, ProgressBar,SurfaceView,TextView,ViewGroup,ViewStub

View派生出的间接子类有:AbsListView,AbsSeekBar, AbsSpinner, AbsoluteLayout, AdapterView,AdapterViewAnimator, AdapterViewFlipper, AppWidgetHostView, AutoCompleteTextView,Button,CalendarView, CheckBox, CheckedTextView, Chronometer, CompoundButton

ViewGroup派生出的直接子类有:AbsoluteLayout,AdapterView,FragmentBreadCrumbs,FrameLayout,LinearLayout,RelativeLayout,SlidingDrawer;

ViewGroup派生出的间接子类有:AbsListView,AbsSpinner, AdapterViewAnimator, AdapterViewFlipper, AppWidgetHostView, CalendarView, DatePicker, DialerFilter, ExpandableListView, Gallery, GestureOverlayView,GridView,HorizontalScrollView, ImageSwitcher,ListView,

当然,随着Android版本不断地更新,这些派生出来的子类也是在不段增加的!


END

原文发布于微信公众号 - 项勇(xiangy_life)

原文发表时间:2017-09-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏项勇

笔记22 | 学习整理开源APP(BaseAnimation)程序源码“中的通讯录效果(三)

1544
来自专栏mathor

GUI编程

 AWT(Abstract Window Toolkit)包含了很多类和接口,用于Java Application的GUI(Graphics User Inte...

922
来自专栏Android开发实战

Android自定义View系列 (从小白做起) 一: 初识

很多的Android入门程序猿来说对于自定义View,可能都是比较恐惧的,其实没那么难,写的多了也就熟练了。 高手之路也是从小白做起的。

762
来自专栏lzj_learn_note

自定义无限循环ViewPager(一)――ViewPager初始化源码解析

大部分app首页一般都会有个无限循环的广告轮播位,通常都是采用ViewPager来实现的,对此大家肯定不会感到陌生。而关于无限循环的ViewPager的实现,一...

1343
来自专栏Coding迪斯尼

VUE+WebPack游戏设计:&#39;乘法防线&#39;游戏设计

1152
来自专栏Python攻城狮

Markdown-认识与使用1.简介2.使用一级标题3.设置Markdown编辑

Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用。看到这里请不要被「标记」、「语言」所迷惑,Markdo...

721
来自专栏JackieZheng

可视化(番外篇)——SWT总结

  本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物、有何用,SWT中...

19510
来自专栏AndroidTv

View.animate()动画ViewPropertyAnimator原理解析

这次想来讲讲 View.animate(),这是一种超好用的动画实现方式,用这种方式来实现常用的动画效果非常方便,但在某些场景下会有一个坑,所以这次就来梳理一下...

3925
来自专栏HT

基于HTML5和WebGL的碰撞测试

这是公司大神写的一个放官网上给用户学习的例子,我一开始真的不知道这是在干嘛,就只是将三个形状图元组合在一起,然后可以同时旋转、放大缩小这个三个图形,点击“Ani...

2269
来自专栏everhad

虾扯蛋:Android View动画 Animation不完全解析

本文结合一些周知的概念和源码片段,对View动画的工作原理进行挖掘和分析。以下不是对源码一丝不苟的分析过程,只是以搞清楚Animation的执行过程、如何被周期...

2189

扫码关注云+社区