Andoird 自定义ViewGroup实现竖向Viewpager

Viewpager只能横向滑动,如果是要竖向滑动呢,那么立马会想到ScrollView ,但是都知道ScrollView滑动并没有判断一页一页分屏滑动,今天来自定义一个ViewGroup实现这个功能。

先看效果:
这里写图片描述

布局文件

<?xml version="1.0" encoding="utf-8"?>
<com.example.apple.Custom.VerticalViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/custom"
    android:layout_height="match_parent"
    tools:context="com.example.apple.Custom.VerticalActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@mipmap/bg1" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@mipmap/bg2" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@mipmap/bg3" />


</com.example.apple.Custom.VerticalViewPager>


关键自定义类

package com.example.apple.Custom;

import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ScrollView;
import android.widget.Scroller;

/**
 * Created by apple on 17/9/16.
 */

public class VerticalViewPager extends ViewGroup {


    OnPageChangeListener lis;
    int mScreenHeight;//屏幕的高
    Scroller mscroller;
    int startScroll;
    int downY;
    int lastPos = -1;
    boolean isTouchDown;


    public VerticalViewPager(Context context) {
        super(context);
        init(context);
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public VerticalViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        mScreenHeight = outMetrics.heightPixels;
        mscroller = new Scroller(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int count = getChildCount();
        for (int i = 0; i < count; ++i) {
            View childView = getChildAt(i);
            measureChild(childView, widthMeasureSpec, mScreenHeight);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed) {
            int childCount = getChildCount();
            MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
            lp.height = mScreenHeight * childCount;
            setLayoutParams(lp);
            for (int i = 0; i < childCount; i++) {
                View child = getChildAt(i);
                if (child.getVisibility() != View.GONE) {
                    child.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);// 调用每个自布局的layout
                }
            }

        }

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int cy = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mscroller.isFinished())
                    return true;
                downY = (int) event.getY();
                startScroll = getScrollY();
                isTouchDown = true;
                break;

            case MotionEvent.ACTION_MOVE:
                int scrollY = getScrollY();
                int dy = downY - cy;
                //向下滑动到最顶端的时候,这里注意,scrollY只用这一个判断,布局会跳动。
                if (dy < 0 && scrollY + dy < 0) {
                    dy = -scrollY;
                }
                // 向上滑动,滑动到最底端的时候,布局不能继续向上移动了,getHeight这个高是整个view的高度,在这里也就是n个屏高度。
                if (dy > 0 && scrollY + dy > getHeight() - mScreenHeight) {
                    dy = getHeight() - mScreenHeight - scrollY;
                }
                scrollBy(0, dy);
                downY = cy;
                break;

            case MotionEvent.ACTION_UP:

                int endScrolly = getScrollY();
                int durscrolly = endScrolly - startScroll;
                if (endScrolly > startScroll) {//向上滑动
                    if (durscrolly > mScreenHeight / 2) {//滑动距离又没有大于半个屏高,切换相应的页面
                        mscroller.startScroll(0, getScrollY(), 0, mScreenHeight - durscrolly);
                    } else {
                        mscroller.startScroll(0, getScrollY(), 0, -durscrolly);
                    }
                }

                if (startScroll > endScrolly) {下滑
                    if (Math.abs(durscrolly) > mScreenHeight / 2) {
                        mscroller.startScroll(0, getScrollY(), 0, -durscrolly - mScreenHeight);
                    } else {
                        mscroller.startScroll(0, getScrollY(), 0, -durscrolly);
                    }
                }
                postInvalidate();
                isTouchDown = false;
                break;
        }

        return true;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mscroller != null && mscroller.computeScrollOffset()) {
            scrollTo(0, mscroller.getCurrY());
            postInvalidate();
        } else {
            if (isTouchDown) return;
            int scrollY = getScrollY();
            int i = scrollY / mScreenHeight;
            if (lastPos == i) return;
            if (lis != null) {
                lis.onPageChange(i);
            }
            lastPos = i;
        }

    }

    public void setPageChangeListener(OnPageChangeListener lis) {
        this.lis = lis;
    }

    public interface OnPageChangeListener {
        void onPageChange(int currentPage);
    }

}

关键代码就这么多,这里只需要注意scroller的用法,滑动工具类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值