package example.com.viewtest.myview; import android.content.Context; import android.support.v4.view.ViewConfigurationCompat; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.Scroller; /** * Created by yzr on 16-2-3. */ public class ScrollerLayout extends ViewGroup { private Scroller mScroller; private int mTouchSlop; private float mXdown; private float mXmove; private float mXLastMove; private int leftBorder; private int rightBorder; private void init(Context context){ mScroller=new Scroller(context); ViewConfiguration configuration=ViewConfiguration.get(context); mTouchSlop= ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); } public ScrollerLayout(Context context) { super(context); init(context); } public ScrollerLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childCount=getChildCount(); for(int i=0;i<childCount;i++){ View child=getChildAt(i); measureChild(child,widthMeasureSpec,heightMeasureSpec); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if(changed) { int childCount=getChildCount(); for(int i=0;i<childCount;i++){ View child=getChildAt(i); child.layout(i*child.getMeasuredWidth(),0,(i+1)*child.getMeasuredWidth(),child.getMeasuredHeight()); } leftBorder=getChildAt(0).getLeft(); rightBorder=getChildAt(childCount-1).getRight(); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mXdown=ev.getRawX(); mXLastMove=mXdown; break; case MotionEvent.ACTION_MOVE: mXmove=ev.getRawX(); float diff=Math.abs(mXmove-mXdown); mXLastMove=mXmove; if(diff>mTouchSlop) return true; break; default: break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: mXmove=event.getRawX(); int scrolledX=(int)(mXLastMove-mXmove); if(getScrollX()+scrolledX<leftBorder){ scrollTo(leftBorder,0); return true; } else if(getScrollX()+getWidth()+scrolledX>rightBorder){ scrollTo(rightBorder-getWidth(),0); return true; } scrollBy(scrolledX,0); mXLastMove=mXmove; break; case MotionEvent.ACTION_UP: int targetIndex=(getScrollX()+getWidth()/2)/getWidth(); int dx=targetIndex*getWidth()-getScrollX(); mScroller.startScroll(getScrollX(),0,dx,0); invalidate(); break; } return super.onTouchEvent(event); } @Override public void computeScroll() { // 第三步,重写computeScroll()方法,并在其内部完成平滑滚动的逻辑 if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } } }