最近学习View相关知识,参考鸿洋大神博客,自己写了个类似竖直方向的viewpager
由于是学习,参照大神博客,目前没有加入高度设置的代码,仅支持全屏显示
大神博客请参考 Andoird 自定义ViewGroup实现竖向引导界面
根据大神博客demo改写,可以上拉到顶部超出view边界,然后弹回,底部同理
直接上代码:VerticalViewPager.java
private int mScreenHeight; //屏幕高度
private int mScrollerStart; //手指按下的时候的scrollY 对应MotionEvent.ACTION_DOWN
private int mScrollerEnd; //手指抬起的时候的scrollY 对应MotionEvent.ACTION_UP
private int mLastY;
private VelocityTracker mVelocityTracker; //速度监测
private Scroller mScroller; //滑动helper
private boolean isScrolling = false; //滑动状态
private int currentPage; //当前显示的页面index
对外提供一个一个OnPageChangeListener监听页面改变
private OnPageChangeListener mPageChangeListener;
public interface OnPageChangeListener {
void onPageChange(int currentPage);
}
首先初始化的时候获取屏幕高度,并初始化scroller
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
mScreenHeight = metrics.heightPixels;
mScroller = new Scroller(context);
重写layout,将child按照从上到下的顺序排列,高度为屏幕高度
MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
layoutParams.height = childCount * mScreenHeight;
setLayoutParams(layoutParams);
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() != GONE) {
childView.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);
}
}
处理点击事件
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isScrolling) {
return super.onTouchEvent(event);
}
int action = event.getAction();
int y = (int) event.getY();
obtainVelocityTracker(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
mScrollerStart = getScrollY();
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
int dy = y - mLastY;
scrollBy(0, -dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mScrollerEnd = getScrollY();
int dScrollY = mScrollerEnd - mScrollerStart;
if (dScrollY < 0) { //向上
if (mScrollerEnd < 0) {
mScroller.startScroll(0, getScrollY(), 0, -getScrollY());
postInvalidate();
} else {
if (canScrollPre(dScrollY)) {
mScroller.startScroll(0, getScrollY(), 0, -(mScreenHeight + dScrollY));
postInvalidate();
} else {
mScroller.startScroll(0, getScrollY(), 0, -dScrollY);
postInvalidate();
}
}
} else { //向下
if (mScrollerEnd > getHeight() - mScreenHeight) {
mScroller.startScroll(0, getScrollY(), 0,- mScreenHeight + getHeight() - getScrollY());
postInvalidate();
} else {
if (canSrollNext(dScrollY)) {
mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - dScrollY);
postInvalidate();
} else {
mScroller.startScroll(0, getScrollY(), 0, -dScrollY);
postInvalidate();
}
}
}
isScrolling = true;
postInvalidate();
recycleVelocity();
break;
}
return true;
}
最后贴上整个代码
package com.example.arvin.myapplication.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Scroller;
/**
* Created by arvin on 2016/2/28.
*/
public class VerticalViewPager extends ViewGroup {
private int mScreenHeight;
private int mScrollerStart;
private int mScrollerEnd;
private int mLastY;
private VelocityTracker mVelocityTracker;
private Scroller mScroller;
private boolean isScrolling = false;
private int currentPage;
private OnPageChangeListener mPageChangeListener;
public interface OnPageChangeListener {
void onPageChange(int currentPage);
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
mScreenHeight = metrics.heightPixels;
mScroller = new Scroller(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
if (changed) {
MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
layoutParams.height = childCount * mScreenHeight;
setLayoutParams(layoutParams);
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() != GONE) {
childView.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isScrolling) {
return super.onTouchEvent(event);
}
int action = event.getAction();
int y = (int) event.getY();
obtainVelocityTracker(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
mScrollerStart = getScrollY();
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
int dy = y - mLastY;
scrollBy(0, -dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mScrollerEnd = getScrollY();
int dScrollY = mScrollerEnd - mScrollerStart;
if (dScrollY < 0) { //向上
if (mScrollerEnd < 0) {
mScroller.startScroll(0, getScrollY(), 0, -getScrollY());
postInvalidate();
} else {
if (canScrollPre(dScrollY)) {
mScroller.startScroll(0, getScrollY(), 0, -(mScreenHeight + dScrollY));
postInvalidate();
} else {
mScroller.startScroll(0, getScrollY(), 0, -dScrollY);
postInvalidate();
}
}
} else { //向下
if (mScrollerEnd > getHeight() - mScreenHeight) {
mScroller.startScroll(0, getScrollY(), 0,- mScreenHeight + getHeight() - getScrollY());
postInvalidate();
} else {
if (canSrollNext(dScrollY)) {
mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - dScrollY);
postInvalidate();
} else {
mScroller.startScroll(0, getScrollY(), 0, -dScrollY);
postInvalidate();
}
}
}
isScrolling = true;
postInvalidate();
recycleVelocity();
break;
}
return true;
}
private boolean canScrollPre(int dscollY) {
return dscollY <= -mScreenHeight / 2 || Math.abs(getVelocity()) > 600;
}
private boolean canSrollNext(int dscollY) {
return dscollY >= mScreenHeight / 2 || Math.abs(getVelocity()) > 600;
}
private void obtainVelocityTracker(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
postInvalidate();
} else {
isScrolling = false;
int position = getScrollY() / mScreenHeight;
if (position != currentPage) {
if (mPageChangeListener != null) {
currentPage = position;
mPageChangeListener.onPageChange(currentPage);
}
}
}
}
private int getVelocity() {
mVelocityTracker.computeCurrentVelocity(1000);
return (int) mVelocityTracker.getYVelocity();
}
private void recycleVelocity() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
public void setOnPageChangeListener(OnPageChangeListener listener) {
this.mPageChangeListener = listener;
}
}
谢谢观赏