[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 条评论
登录 后参与评论

相关文章

来自专栏分享达人秀

Intent 属性详解(上)

Android应用将会根据Intent来启动指定组件,至于到底启动哪个组件,则取决于Intent的各属性。本期将详细介绍Intent的各属性值,以及 A...

16910
来自专栏三好码农的三亩自留地

Android九宫格控件-可在ListView和RecyclerView中使用

熟悉Android App开发的同学,肯定都清楚,如果要显示多张图片,类似九宫格,可以用GridView或者GridLayout来做,但是如果需求要求在List...

872
来自专栏Android-薛之涛

Android 事件分发机制

事件分发机制在android中非常常见,比如:手势滑动,自定义View,多点触控都有它的身影。事件分发的顺序是:Activity->GroupView->Vie...

541
来自专栏郭霖

Android系统联系人全特效实现(下),字母表快速滚动

在上一篇文章中,我和大家一起实现了类似于Android系统联系人的分组导航和挤压动画功能,不过既然文章名叫做《Android系统联系人全特效实现》,那么没有快速...

1918
来自专栏iOS开发笔记

cordova插件- Contacts

添加插件 $cordova plugin add cordova-plugin-contacts 图 8出现如上则添加成功 插件的使用 Methods navi...

3275
来自专栏jianhuicode

事件分发机制学习

0x01 事件分发机制中三个重要的函数  View事件机制有哪几个重要函数?dispatchTouchEvent(),onInterceptTouchEvent...

16510
来自专栏Android中高级开发

Android开发之漫漫长途 XIV——ListView

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索...

873
来自专栏移动开发

关于通知的一些小问题

最近做下载,有一个通知显示进度的需求。这个过程中碰到一些问题,这里总结下,方便大家排查。

1064
来自专栏三流程序员的挣扎

RecyclerView 使用总结

自定义类继承 RecyclerView.ItemDecoration,重写回调方法

1022
来自专栏用户3030674的专栏

Android事件分发机制详解

1、经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等

614

扫码关注云+社区