Android 使用Scroller自动滚动第一种实现



源码下载 , 效果图如下:

Android 使用Scroller自动滚动第一种实现_第1张图片


1. 自定义视图继承自ViewGroup,覆写onMeasure,onLayout,之前文章介绍过覆写这两个方法。

2. 提供两个方法供两个button使用,向左向右移动。调用startScroll (int startX, int startY, int dx, int dy)方法, 以提供的起始点和将要滑动的距离开始滚动。滚动会使用缺省值250ms作为持续时间。

3. 设置滚动的便宜量childView.offsetLeftAndRight(leftAndRightOffset);

4. 调用invalidate()进行重绘

5. 延迟短暂时间,返回执行3,4步骤


public class CustomViewGroup extends ViewGroup {

    // ===========================================================
    // Constants
    // ===========================================================
    
    private static final int DELAY_MILLIS = 1000 / 60;
    
    // ===========================================================
    // Fields
    // ===========================================================
    
    // 记录上次滚动的位置,用于计算滚动偏移量
    private int mOffsetX = 0;
    
    private Scroller mScroller = new Scroller(getContext());
    
    private Handler mHandler = new Handler();
    
    private Runnable mScrollerRunnable = new ScrollerRunnable();
    
    // 每次滚动的距离
    private int mScrollWidth = 300;
    
    // ===========================================================
    // Constructors
    // ===========================================================

    public CustomViewGroup(Context context) {
        super(context);
    }


    public CustomViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public CustomViewGroup(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    // ===========================================================
    // Getter & Setter
    // ===========================================================

    /**
     * 向右滚动
     */
    public void scrollToRight() {
        scroll(true);
    }
    
    /**
     * 向左滚动
     */
    public void scrollToLeft() {
        scroll(false);
    }
    
    // ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        
        setMeasuredDimension(widthSize, heightSize);
    }
    
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            
            int measuredWidth = childView.getMeasuredWidth();
            int measuredHeight = childView.getMeasuredHeight();
            
            childView.layout(mOffsetX, 0, mOffsetX + measuredWidth, measuredHeight);
        }
    }
    
    // ===========================================================
    // Methods
    // ===========================================================
    
    private void scroll(boolean scrollToRight) {
        // 向右滚动举例是正值,反之负值
        int scrollWidth = scrollToRight ? mScrollWidth: -mScrollWidth;
        
        // 此次滚动的X轴终点位置
        int scrollFinalX = mOffsetX + scrollWidth;
        
        // 不能移出边界
        if (scrollFinalX > 300 || scrollFinalX < 0) {
            return;
        }

        // 清除
        mHandler.removeCallbacks(mScrollerRunnable);
        
        // 触发开始滚动
        mScroller.startScroll(mOffsetX, 0, scrollWidth, 0);
        
        // 子线程中间隔段时间重绘视图
        mHandler.post(mScrollerRunnable);
    }
    
    /**
     * 设置view滚动后的x坐标的位置
     * 
     * @param offsetX
     */
    private void setOffsetX(int offsetX) {
        if (offsetX == mOffsetX) {
            return;
        }
        
        final int leftAndRightOffset = offsetX - mOffsetX;
        
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            childView.offsetLeftAndRight(leftAndRightOffset);
        }
        
        mOffsetX = offsetX;
    }
    
    
    
    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================

    private class ScrollerRunnable implements Runnable {

        @Override
        public void run() {

            final Scroller scroller = mScroller;
            
            if (scroller.computeScrollOffset()) {
                
                setOffsetX(scroller.getCurrX());
                
                // 位置发生偏移,重绘
                invalidate();
                
                // 每过间隔时间,再次执行当前子线程
                mHandler.postDelayed(this, DELAY_MILLIS);
            }
        }

    }
    
    
    
}




扩展:

学习下Scroller原理



原文地址:http://blog.csdn.net/love_world_/article/details/8126234



你可能感兴趣的:(Android 使用Scroller自动滚动第一种实现)