Android Scroller容易用法

Android Scroller简单用法

1.知识点

  • 在了解Scorller类之前应先知道View的ScrollTo(int x, int y)/ScrollBy(int x, int y)之间的区别,了解什么是视图坐标,什么是布局坐标。之后我们来看一下Scroller的源码。

Scoller一般用在自定义View中

public class Scroller  {  
  
    private int mStartX;    //起始坐标点 ,  X轴方向  
    private int mStartY;    //起始坐标点 ,  Y轴方向  
    private int mCurrX;     //当前坐标点  X轴, 即调用startScroll函数后,经过一定时间所达到的值  
    private int mCurrY;     //当前坐标点  Y轴, 即调用startScroll函数后,经过一定时间所达到的值  
     
    private float mDeltaX;  //应该继续滑动的距离, X轴方向  
    private float mDeltaY;  //应该继续滑动的距离, Y轴方向  
    private boolean mFinished;  //是否已经完成本次滑动操作, 如果完成则为 true  
  
    //构造函数  
    public Scroller(Context context) {  
        this(context, null);  
    }  
    public final boolean isFinished() {  
        return mFinished;  
    }  
    //强制结束本次滑屏操作  
    public final void forceFinished(boolean finished) {  
        mFinished = finished;  
    }  
    public final int getCurrX() {  
        return mCurrX;  
    }  
     /* Call this when you want to know the new location.  If it returns true, 
     * the animation is not yet finished.  loc will be altered to provide the 
     * new location. */    
    //根据当前已经消逝的时间计算当前的坐标点,保存在mCurrX和mCurrY值中  
    public boolean computeScrollOffset() {  
        if (mFinished) {  //已经完成了本次动画控制,直接返回为false  
            return false;  
        }  
        int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);  
        if (timePassed < mDuration) {  
            switch (mMode) {  
            case SCROLL_MODE:  
                float x = (float)timePassed * mDurationReciprocal;  
                ...  
                mCurrX = mStartX + Math.round(x * mDeltaX);  
                mCurrY = mStartY + Math.round(x * mDeltaY);  
                break;  
            ...  
        }  
        else {  
            mCurrX = mFinalX;  
            mCurrY = mFinalY;  
            mFinished = true;  
        }  
        return true;  
    }  
    //开始一个动画控制,由(startX , startY)在duration时间内前进(dx,dy)个单位,即到达坐标为(startX+dx , startY+dy)出  
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {  
        mFinished = false;  
        mDuration = duration;  
        mStartTime = AnimationUtils.currentAnimationTimeMillis();  
        mStartX = startX;       mStartY = startY;  
        mFinalX = startX + dx;  mFinalY = startY + dy;  
        mDeltaX = dx;            mDeltaY = dy;  
        ...  
    }  
}  

一些方法介绍

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()中,用来判断是否滚动是否结束。
  • View的computeScroll()方法使用,此方法在绘制View的每一个子view时都被调用

2.举例


实现下拉刷新的效果
Android Scroller容易用法        Android Scroller容易用法
 主要代码:
public class CustomView extends RelativeLayout {

	private static final String TAG = "CustomView";

	private Scroller mScroller;
	private GestureDetector mGestureDetector;
	public boolean flag = true;
	public StateListener stateListener;
	public CustomView(Context context) {
		this(context, null);
	}
	
	public CustomView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setClickable(true);
		setLongClickable(true);
		mScroller = new Scroller(context);
		mGestureDetector = new GestureDetector(context, new CustomGestureListener());
	}
	public interface StateListener
	{
		public void changeText();
		public void recoverText();
	}
	public void setStateListener(StateListener statelistener)
	{
		this.stateListener = statelistener;
	}
	//调用此方法滚动到目标位置
	public void smoothScrollTo(int fx, int fy) {
		int dx = fx - mScroller.getFinalX();
		int dy = fy - mScroller.getFinalY();
		smoothScrollBy(dx, dy);
	}

	//调用此方法设置滚动的相对偏移
	public void smoothScrollBy(int dx, int dy) {

		//设置mScroller的滚动偏移量
		mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
		invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
	}
	
	//在绘制View时,会在draw()过程调用该方法。
	@Override
	public void computeScroll() {
	
		//先判断mScroller滚动是否完成
		if (mScroller.computeScrollOffset()) {
		
			//这里调用View的scrollTo()完成实际的滚动
			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			
			//必须调用该方法,否则不一定能看到滚动效果
			postInvalidate();
		}
		super.computeScroll();
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_UP :
			Log.i(TAG, "get Sy" + getScrollY());
			System.out.println(getScrollX()+"x--"+getScrollY()+"y");
			smoothScrollTo(0, 0);
			System.out.println("up");
			break;
		default:
			int distance = getScrollY();
			System.out.println("distance"+distance);
			if(distance <= 0)
			{
				flag = true;
				if(distance > -200)
				{
					stateListener.recoverText();
				}
				else if(distance < -200)
				{
					stateListener.changeText();
				}
				return mGestureDetector.onTouchEvent(event);
			}else
			{
				flag = false;
				return false;
			}
		}
		return super.onTouchEvent(event);
	}
	
	class CustomGestureListener implements GestureDetector.OnGestureListener {

		@Override
		public boolean onDown(MotionEvent e) {
			// TODO Auto-generated method stub
			return true;
		}

		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			if(flag)
			{int dis = (int)((distanceY-0.5)/4);
			Log.i(TAG, dis + ".");
			smoothScrollBy(0, dis);}
			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			// TODO Auto-generated method stub
			e1.getY();
			e2.getY();
			System.out.println(e1.getY()+"------"+e2.getY());
			return false;
		}
		
	}
}