Android进阶篇左右滑屏

public class PageDragView extends ViewGroup{

    private static final String TAG = PageDragView.class.getSimpleName();   
    /**
     * 用来追踪触摸事件(flinging事件和其他手势事件)的速率
     * 用obtain()函数来获得类的实例,
     * 用addMovement(MotionEvent)函数将motion event加入到VelocityTracker类实例中,
     * 当你使用到速率时,使用computeCurrentVelocity(int)初始化速率的单位,
     * 并获得当前的事件的速率,
     * 然后使用getXVelocity() 或getXVelocity()获得横向和竖向的速率
     */
    private VelocityTracker mVelocityTracker;
    private static final int SNAP_VELOCITY = 600;    
    //滚动事件
    private Scroller  mScroller;                        
    private int mCurScreen;                            
    private int mDefaultScreen = 0;                        
    //临时存储Motion的X坐标
    private float mLastMotionX; 
    
    private OnViewChangeListener mOnViewChangeListener;//监听事件
     
    public PageDragView(Context context) {
        super(context);
        init(context);
    }
    
    public PageDragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    
    public PageDragView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }
    
    private void init(Context context){
        mCurScreen = mDefaultScreen;    
        mScroller = new Scroller(context); 
    }

    /**onMeasure->onLayout*/
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
         Log.i(TAG, "changed= " + changed);
         if (changed) {    
                int childLeft = 0;    
                final int childCount = getChildCount();    
                    
                for (int i=0; i<childCount; i++) {    
                    final View childView = getChildAt(i);    
                    if (childView.getVisibility() != View.GONE) {
                        Log.i(TAG, "childLeft= " + childLeft);
                        final int childWidth = childView.getMeasuredWidth();    
                        childView.layout(childLeft, 0,     
                                childLeft+childWidth, childView.getMeasuredHeight());    
                        childLeft += childWidth;    
                    }    
                }    
            }    
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int width = MeasureSpec.getSize(widthMeasureSpec);       
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);      
        
        Log.i(TAG, "widthMeasureSpec= " + widthMeasureSpec);
        Log.i(TAG, "heightMeasureSpec= " + heightMeasureSpec);
        final int count = getChildCount();       
        for (int i = 0; i < count; i++) {       
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);       
        }         
        scrollTo(mCurScreen * width, 0);
    }

    //滚动操作
    public void snapToScreen(int whichScreen) {    
        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));    
        if (getScrollX() != (whichScreen*getWidth())) {    
            final int delta = whichScreen*getWidth()-getScrollX();    
            mScroller.startScroll(getScrollX(), 0,delta, 0, Math.abs(delta)*2);
            mCurScreen = whichScreen;    
            invalidate();       // Redraw the layout    
            if (mOnViewChangeListener != null)
            {
                mOnViewChangeListener.OnViewChange(mCurScreen);
            }
        }    
    } 

     public void snapToDestination() {    
        final int screenWidth = getWidth();    
        final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;    
        snapToScreen(destScreen);    
     }  
    

    @Override
    public void computeScroll() {
        // TODO Auto-generated method stub
        if (mScroller.computeScrollOffset()) {    
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
            postInvalidate();    
        }   
    }

    //View的触屏事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub           
        final int action = event.getAction();    
        final float x = event.getX();    
        final float y = event.getY();    
        
        switch (action) {    
        case MotionEvent.ACTION_DOWN: 
            if (mVelocityTracker == null) {    
                mVelocityTracker = VelocityTracker.obtain();    
                mVelocityTracker.addMovement(event); 
            }
            if(!mScroller.isFinished()){    
                mScroller.abortAnimation();    
            }    
            mLastMotionX = x;      
            Log.i(TAG, "mLastMotionX= " + mLastMotionX);
            break;    
            
        case MotionEvent.ACTION_MOVE:  
            //滑动的距离
            int deltaX = (int)(mLastMotionX - x);
            if (IsCanMove(deltaX)){
                 if (mVelocityTracker != null){
                          mVelocityTracker.addMovement(event); 
                   }   
                   mLastMotionX = x;   
                   //在当前位置,继续偏移(x,y)个单位
                   scrollBy(deltaX, 0);    
            }
            break;    
                
        case MotionEvent.ACTION_UP:       
            int velocityX = 0;
            if (mVelocityTracker != null){
                mVelocityTracker.addMovement(event); 
                mVelocityTracker.computeCurrentVelocity(1000);  
                //X方向滑动的速率
                velocityX = (int) mVelocityTracker.getXVelocity();
            }
            Log.i(TAG, "velocityX= " + velocityX);
            /**mCurScreen 当前屏幕的下标值*/
            if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {       
                snapToScreen(mCurScreen - 1);       
            } else if (velocityX < -SNAP_VELOCITY       
                    && mCurScreen < getChildCount() - 1) {       
                snapToScreen(mCurScreen + 1);       
            } else {       
                snapToDestination();       
            }      
            if (mVelocityTracker != null) {       
                mVelocityTracker.recycle();       
                mVelocityTracker = null;       
            }       
            break;      
        }    
        return true;    
    }
    
    private boolean IsCanMove(int deltaX){
        //getScrollX() 视图起始坐标偏移值
        if(getScrollX() <= 0 && deltaX < 0 ){
            return false;
        }
        if(getScrollX() >=  (getChildCount() - 1) * getWidth() && deltaX > 0){
            return false;
        }
        return true;
    }
    
    public void SetOnViewChangeListener(OnViewChangeListener listener){
        mOnViewChangeListener = listener;
    }
    
    public interface OnViewChangeListener {
        /**监听事件 
         * @params view 当前的View
         * @return
         */
        public void OnViewChange(int view);
    }
}
原文地址:https://www.cnblogs.com/gongcb/p/2534968.html