自定义竖直方向的ViewPager

最近学习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;
    }
}

谢谢观赏

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值