自定义一个垂直的布局
package com.zyh.verticalscrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
public class VerticalSrcollView extends ViewGroup {
public VerticalSrcollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private Context cx;
public VerticalSrcollView(Context context) {
super(context);
this.cx = context;
init();
}
public VerticalSrcollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.cx = context;
init();
}
private void init() {
scroller = new Scroller(cx);
detector = new GestureDetector(cx, new OnGestureListener() {
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public void onShowPress(MotionEvent e) {
}
/**
* 当手指正常滑动时回调
*/
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if ((distanceY < 0 && curId == 0) || (distanceY > 0 && curId == getChildCount() - 1)) {// 首页跟末尾页超出边界
return false;
}
scrollBy(0, (int) distanceY);
return false;
}
public void onLongPress(MotionEvent e) {
}
/**
* 当快速滑动式回调
*/
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
System.out.println("vY:" + velocityY);
System.out.println("cr:" + curId);
if (velocityY > 0 && curId > 0) {
moveToDest(curId - 1);
} else if (velocityY < 0 && curId < getChildCount() - 1) {
moveToDest(curId + 1);
} else {
moveToDest(curId);
}
isFling = true;
return false;
}
public boolean onDown(MotionEvent e) {
return false;
}
});
}
/**
* 对子view进行排列布局
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
View view = this.getChildAt(i);
view.layout(0, i * getHeight(), getWidth(), (i + 1) * getHeight());
}
}
/**
* 必须对子View进行measure
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
view.measure(widthMeasureSpec, heightMeasureSpec);
}
}
private GestureDetector detector;
private Scroller scroller;
private int curId;// 当前子View的Id
private boolean isFling = false; // 是否发生快速滑动
@Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);// 交给手势识别器
switch (event.getAction()) {
case MotionEvent.ACTION_UP:// 手指抬起
if (!isFling) moveToDest();
isFling = false;
break;
default:
break;
}
return true;
}
/**
* ViewGroup的内容移动到合适位置
*/
private void moveToDest() {
// 计算当前子view的id
int destId = (getHeight() / 2 + getScrollY()) / getHeight();
moveToDest(destId);
}
/**
* 将指定下标destId的控件移到屏幕
* @param destId
*/
private void moveToDest(int destId) {
curId = destId;
if (destId > getChildCount() - 1) destId = getChildCount() - 1;
int distance = destId * getHeight() - getScrollY();// 需要移动的距离
// scrollBy(0, distance);
scroller.startScroll(0, getScrollY(), 0, distance);
invalidate();// 刷新视图,执行computeScroll()
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(0, scroller.getCurrY());
invalidate();
}
}
public void setOnPageScrollListener(IPageChangeListener changeListener) {
this.pageChangeListener = changeListener;
}
private IPageChangeListener pageChangeListener;
/**
* 页面滑动监听器
* @author zyh
*/
public interface IPageChangeListener {
public void changeTo(int pageId);
}
}