zoukankan      html  css  js  c++  java
  • [Android Pro] Scroller使用分析

    reference to : http://blog.csdn.net/a910626/article/details/51548840

    一.Scroller是什么?

    • Android里 Scroller类是为了实现View平滑滚动的一个Helper类。通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context)。设置mScroller滚动的位置时,并不会导致View的滚动,通常是用mScroller记录/计算View滚 动的位置,再重写View的computeScroll(),完成实际的滚动。

    • Scroller只是个计算器,提供插值计算,让滚动过程具有动画属性,但它并不是UI,也不是辅助UI滑动,反而是单纯地为滑动提供计算。

    • 无论从构造方法还是其他方法,以及Scroller的属性可知,其并不会持有View,辅助ViewGroup滑动。

    • Scroller只是提供计算,那谁来调用computeScroll使得ViewGroup滑动

    • computeScroll也不是来让ViewGroup滑动的,真正让ViewGroup滑动的是scrollTo,scrollBy。computeScroll的作用是计算ViewGroup如何滑动。而computeScroll是通过draw来调用的。

    • computeScroll和Scroller都是计算,两者有啥关系?没有直接的关系。computeScroll和Scroller要 是飞得拉关系的话,那就是computeScroll可以参考Scroller计算结果来影响scrollTo,scrollBy,从而使得滑动发生改 变。也就是Scroller不会调用computeScroll,反而是computeScroll调用Scroller。

    • 滑动时连续的,如何让Scroller的计算也是连续的?这个就问到了什么时候调用computeScroll了,如上所说 computeScroll调用Scroller,只要computeScroll调用连续,Scroller也会连续,实质上 computeScroll的连续性又invalidate方法控制,scrollTo,scrollBy都会调用invalidate,而 invalidate回去触发draw,从而computeScroll被连续调用,综上,Scroller也会被连续调用,除非invalidate停 止调用。

    • computeScroll如何和Scroller的调用过程保持一致?computeScroll参考Scroller影响 scrollTo,scrollBy,实质上,为了不重复影响scrollTo,scrollBy,那么Scroller必须终止计算 currX,currY。要知道计算有没有终止,需要通过mScroller.computeScrollOffset()

    二.这个知识应用场景是?可以解决什么问题?

      我们在需求实现时,经常遇到view滑动的情况,而scrollTo、scrollBy方法都可以实现view的滑动,但是效果是瞬间完成的, 用户体验并不好,我们可以使用scroller或者smoothScrollto(内部也是scroller实现的)来实现平滑移动的效果。常见于自定义 view中。

    三.该类的常见API?

    mScroller.getCurrX() //获取mScroller当前水平滚动的位置  
    mScroller.getCurrY() //获取mScroller当前竖直滚动的位置  
    mScroller.getFinalX() //获取mScroller最终停止的水平位置  
    mScroller.getFinalY() //获取mScroller最终停止的竖直位置  
    mScroller.setFinalX(int newX) //设置mScroller最终停留的水平位置,没有动画效果,直接跳到目标位置  
    mScroller.setFinalY(int newY) //设置mScroller最终停留的竖直位置,没有动画效果,直接跳到目标位置  
    
    //滚动,startX, startY为开始滚动的位置,dx,dy为滚动的偏移量, duration为完成滚动的时间  
    mScroller.startScroll(int startX, int startY, int dx, int dy) //使用默认完成时间250ms  
    mScroller.startScroll(int startX, int startY, int dx, int dy, int duration)  
    
    mScroller.computeScrollOffset() //返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。这是一个很重要的方法,通常放在View.computeScroll()中,用来判断是否滚动是否结束。  

    四.常规的用法是什么?

      Scroller的基本用法其实还是比较简单的,主要可以分为以下几个步骤:
    1. 创建Scroller的实例
    2. 调用startScroll()方法来初始化滚动数据并刷新界面
    3. 重写computeScroll()方法,并在其内部完成平滑滚动的逻辑

    五.使用时的难点在哪里?

      使用的难点在于startScroll的参数含义,然后根据参数含义给出合适的值,因为这个过程涉及android中坐标计算,所以较为复杂。

           // void android.widget.Scroller.startScroll(int startX, int startY, int dx, int dy, int duration)
            // 第一个参数是起始移动的x坐标值,
            // 第二个是起始移动的y坐标值,
            // 第三个第四个参数都是移到某点的坐标值-初始的坐标值,即移动的距离值
            // 而duration 当然就是执行移动的时间。

    六.一个案例:来自《android群英传》

    public class ScrollerDragView extends View {
        private Scroller mScroller;
        private int mLastX;
        private int mLastY;
    
        public ScrollerDragView(Context context) {
            super(context);
            initView(context);
        }
    
    
        public ScrollerDragView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
        }
    
        private void initView(Context context) {
            setBackgroundColor(Color.BLUE);
            mScroller = new Scroller(context);
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int x = (int) event.getX();
            int y = (int) event.getY();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mLastX = (int) event.getX();
                    mLastY = (int) event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int offsetX = x - mLastX;
                    int offsetY = y - mLastY;
                    // 貌似使用了getParent,就不再需要重置x,y的坐标了
                    ((View)getParent()).scrollBy(-offsetX, -offsetY);
                    break;
                case MotionEvent.ACTION_UP:
                    View viewGroup = (View) getParent();
                    mScroller.startScroll(viewGroup.getScrollX(),
                            viewGroup.getScrollY(),
                            -viewGroup.getScrollX(),
                            -viewGroup.getScrollY());
                    invalidate();
                    break;
            }
            return true;
        }
    
        /**
         * 这里不需要特别的理解,只要使用Scroller,这里都是一样的
         */
        @Override
        public void computeScroll() {
            super.computeScroll();
            if (mScroller.computeScrollOffset()) {
                ((View)getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                invalidate();
            }
        }
    }
     
  • 相关阅读:
    毕业设计进度16
    毕业设计进度15
    毕业设计进度14
    毕业设计进度13
    毕业设计进度12
    毕业设计进度11
    JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
    Media Queries详解
    css 选择器
    css内容样式属性
  • 原文地址:https://www.cnblogs.com/0616--ataozhijia/p/6113099.html
Copyright © 2011-2022 走看看