《Android进阶之光》Horizontal 读书笔记
public class HorizontalView extends ViewGroup {
private int lastInterceptX;
private int lastInterceptY;
private int lastX;
private int lastY;
private int childWidth;
private int curIndex;
private Scroller scroller;
private VelocityTracker tracker;
public HorizontalView (Context context) {
this (context, null );
}
public HorizontalView (Context context, AttributeSet attrs) {
this (context, attrs, 0 );
}
public HorizontalView (Context context, AttributeSet attrs, int defStyleAttr) {
super (context, attrs, defStyleAttr);
init();
}
private void init () {
scroller = new Scroller(getContext());
tracker = VelocityTracker.obtain();
}
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super .onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthSpec = MeasureSpec.getMode(widthMeasureSpec);
int heightSpec = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (getChildCount() == 0 ) {
setMeasuredDimension(0 , 0 );
}
View childOne = getChildAt(0 );
int childWidth = childOne.getMeasuredWidth();
int childHeight = childOne.getMeasuredHeight();
if (widthSpec == MeasureSpec.AT_MOST) {
widthSize = childWidth * getChildCount();
}
if (heightSpec == MeasureSpec.AT_MOST) {
heightSize = childHeight;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout (boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
int left = 0 ;
View child;
for (int i = 0 ; i < childCount; i++) {
child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
int width = child.getMeasuredWidth();
childWidth = width;
child.layout(left, 0 , left + width, child.getMeasuredHeight());
left += width;
}
}
}
@Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
boolean intercept = false ;
int x = (int ) ev.getX();
int y = (int ) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
intercept = false ;
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
break ;
case MotionEvent.ACTION_MOVE:
int deltaX = x - lastInterceptX;
int deltaY = y - lastInterceptY;
intercept = Math.abs(deltaX) - Math.abs(deltaY) > 0 ;
break ;
case MotionEvent.ACTION_UP:
break ;
}
lastInterceptX = x;
lastInterceptY = y;
lastX = x;
lastY = y;
return intercept;
}
@Override
public boolean onTouchEvent (MotionEvent event) {
int x = (int ) event.getX();
int y = (int ) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
break ;
case MotionEvent.ACTION_MOVE:
int deltaX = x - lastX;
scrollBy(-deltaX, 0 );
break ;
case MotionEvent.ACTION_UP:
int dis = getScrollX() - curIndex * childWidth;
if (Math.abs(dis) > childWidth / 2 ) {
if (dis > 0 ) {
curIndex++;
} else {
curIndex--;
}
} else {
tracker.computeCurrentVelocity(1000 );
float xV = tracker.getXVelocity();
if (xV > 50 ) {
if (xV > 0 ) {
curIndex--;
} else {
curIndex++;
}
}
}
curIndex = curIndex < 0 ? 0 :
curIndex > getChildCount() - 1 ? getChildCount() - 1 : curIndex;
smoothScrollTo(curIndex * childWidth, 0 );
tracker.clear();
break ;
}
lastX = x;
lastY = y;
return super .onTouchEvent(event);
}
@Override
public void computeScroll () {
super .computeScroll();
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
/**
* 弹性滑动
*/
public void smoothScrollTo (int destX, int destY) {
scroller.startScroll(getScrollX(), getScrollY(),
destX - getScrollX(), destY - getScrollY(), 1000 );
invalidate();
}
}