学习使用安卓scroller

来源:互联网 发布:千古乎评证券之星 编辑:程序博客网 时间:2024/05/19 13:56

Android Scroller 解读编写Demo

Scroller是一个专门用于处理滚动效果的工具类,大多数情况下,我们直接使用Scroller的场景并不多,但是很多大家所熟知的控件在内部都是使用Scroller来实现的,如ViewPager、ListView等。而如果能够把Scroller的用法熟练掌握的话,对于之后使用ViewPager更容易上手。

直接上源码,代码已经做了详细解读:

public class ScrollerLayout extends ViewGroup {

/** * 用于完成滚动操作的实例 */private Scroller mScroller;/** * 判定为拖动的最小移动像素数 */private int mTouchSlop;/** * 手机按下时的屏幕坐标 */private float mXDown;/** * 手机当时所处的屏幕坐标 */private float mXMove;/** * 上次触发ACTION_MOVE事件时的屏幕坐标 */private float mXLastMove;/** * 界面可滚动的左边界 */private int leftBorder;/** * 界面可滚动的右边界 */private int rightBorder;public ScrollerLayout(Context context, AttributeSet attr) {    super(context,attr);    // 第一步,创建Scroller的实例    mScroller=new Scroller(context);    ViewConfiguration configuration=ViewConfiguration.get(context);    //能够识别的最小滑动举例 ViewConfiguration.getScaledTouchSlop();    //获取TouchSlop值        mTouchSlop= configuration.getScaledTouchSlop();}//定义View的位置在ViewGroup中的位置//1)参数changed表示view有新的尺寸或位置;//2)参数l表示相对于父view的Left位置;//3)参数t表示相对于父view的Top位置;//4)参数r表示相对于父view的Right位置;//5)参数b表示相对于父view的Bottom位置。.@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {      if(changed){          int childCount=getChildCount();          for (int i=0;i<childCount;i++){              View childView=getChildAt(i);              // 为ScrollerLayout中的每一个子控件在水平方向上进行布局              //layout(a,b,c,d)中的四个参数是相对于父布局定义的              //a和 b 是控件左边缘和上边缘相对于父类控件左边缘和上边缘的距离。             // c 和 d是空间右边缘和下边缘相对于父类控件左边缘和上边缘的距离。              childView.layout(i * childView.getMeasuredWidth(), 0, (i + 1) * childView.getMeasuredWidth(), childView.getMeasuredHeight());          }          // 初始化左右边界值          leftBorder = getChildAt(0).getLeft();          rightBorder = getChildAt(getChildCount() - 1).getRight();      }}//View本身大小多少,由onMeasure()来决定@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    //返回包含View的个数    int childCount=getChildCount();    for(int i=0;i<childCount;i++){        //获取布局中的view        View childView=getChildAt(i);        //规定了每个子view的尺寸,与当前的父View保持一致        measureChild(childView,widthMeasureSpec,widthMeasureSpec);    }}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {    switch (ev.getAction()){        //手指按下        case MotionEvent.ACTION_DOWN:            //获取绝对坐标,相对于屏幕的X坐标            mXDown = ev.getRawX();            mXLastMove = mXDown;            break;        //手指滑动        case MotionEvent.ACTION_MOVE:            mXMove = ev.getRawX();            float diff = Math.abs(mXMove - mXDown);            mXLastMove = mXMove;            // 当手指拖动值大于TouchSlop值时,认为应该进行滚动,拦截子控件的事件            if (diff > mTouchSlop) {                return true;            }            break;    }    return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()){        case MotionEvent.ACTION_MOVE:            mXMove=event.getRawX();            int scrolledX=(int)(mXLastMove-mXMove);            //getScrollX() 就是当前view的左上角相对于母视图的左上角的X轴偏移量            if(getScrollX()+scrolledX<leftBorder){                scrollTo(leftBorder, 0);                return true;            }else if(getScrollX() + getWidth()+scrolledX >rightBorder){                scrollTo(rightBorder - getWidth(), 0);                return true;            }            scrollBy(scrolledX, 0);            mXLastMove = mXMove;            //手指离开屏幕        case MotionEvent.ACTION_UP:            // 当手指抬起时,根据当前的滚动值来判定应该滚动到哪个子控件的界面            int targetIndex = (getScrollX() + getWidth() / 2) / getWidth();            int dx = targetIndex * getWidth() - getScrollX();            // 第二步,调用startScroll()方法来初始化滚动数据并刷新界面           //invalidate()函数的主要作用是请求View树进行重绘           // startScroll执行过程中即在duration时间内,            // computeScrollOffset 方法会一直返回false,但当动画执行完成后会返回返加true.            mScroller.startScroll(getScrollX(), 0, dx, 0);            invalidate();            break;    }    return super.onTouchEvent(event);}@Overridepublic void computeScroll() {    // 第三步,重写computeScroll()方法,并在其内部完成平滑滚动的逻辑    if (mScroller.computeScrollOffset()) {        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());        //invalidate()函数的主要作用是请求View树进行重绘        invalidate();    }}

activity_main.xml

这里写图片描述

参考:http://blog.csdn.net/guolin_blog/article/details/48719871
http://www.jianshu.com/p/0c863bbde8eb
http://blog.csdn.net/pi9nc/article/details/18764863

原创粉丝点击