滑动翻页实现, 类似Gallery效果
public class GlidePage extends ViewGroup { private float mTouchX; private float mLastMotionX; private int mActivePointerId = -1; private Scroller mScroller; public GlidePage(Context context, AttributeSet attrs) { super(context, attrs); mScroller = new Scroller(context); //initScreen(); // TODO Auto-generated constructor stub } public GlidePage(Context context, AttributeSet attrs, int defStyle) { super(context,attrs,defStyle); mScroller = new Scroller(context); //initScreen(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub int childLeft = 0; final int count = getChildCount(); for(int i = 0; i < count; i++) { final View child = getChildAt(i); if(child.getVisibility() != View.GONE) { final int childWidth = child.getMeasuredWidth(); child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); childLeft += childWidth; } } } @Override protected void dispatchDraw(Canvas canvas) { // TODO Auto-generated method stub final long drawingTime = getDrawingTime(); final int count = getChildCount(); for(int i = 0; i< count; i++) { drawChild(canvas, getChildAt(i), drawingTime); } } @Override public void computeScroll() { // TODO Auto-generated method stub if(mScroller.computeScrollOffset()) { mTouchX = mScroller.getCurrX(); int scrollY = mScroller.getCurrY(); scrollTo((int)mTouchX, scrollY); postInvalidate(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int widthMode = MeasureSpec.getMode(widthMeasureSpec); if(widthMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("GlidePage can only be used in EXACTLY mode."); } final int heightMode = MeasureSpec.getMode(heightMeasureSpec); if(heightMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("GlidePage can only be used in EXACTLY mode."); } final int count = getChildCount(); for(int i = 0; i < count; i++) { getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); } } @Override public boolean onTouchEvent(MotionEvent e) { final int action = e.getAction(); switch(action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mLastMotionX = e.getX(); mActivePointerId = e.getPointerId(0); break; case MotionEvent.ACTION_MOVE: final int pointerIndex = e.findPointerIndex(mActivePointerId); try{ final float x = e.getX(pointerIndex); final float deltaX = mLastMotionX - x; mLastMotionX = x; if(deltaX > 0) { scrollBy((int)deltaX, 0); } else if(deltaX < 0) { scrollBy((int)deltaX,0); } else { awakenScrollBars(); } }catch(ArrayIndexOutOfBoundsException ex) { } break; case MotionEvent.ACTION_UP: int screenWidth = getWidth(); int whichView = (getScrollX() + (screenWidth / 2)) / screenWidth; whichView = Math.max(0, Math.min(whichView, getChildCount() - 1)); int newX = whichView * getWidth(); int delta = newX - getScrollX(); mScroller.startScroll(getScrollX(), 0, delta, 0); invalidate(); break; case MotionEvent.ACTION_CANCEL: break; case MotionEvent.ACTION_POINTER_UP: break; } return true; } }