自定义ViewGroup实现纵向滑动切换的ViewPager

实现了纵向切换,同时支持多手指操作,过滤横向事件,直接复制过去即可使用,(注意:外面要裹一个RelativeLayout,其他布局暂时不支持)经本人多次测试未发现有错误,若您发现有错误望指出,在下面留言即可,谢谢合作!

package com.example.k.optimization_myviewgroup;

import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * Created by k on 2016/8/10.
 */
public class custom_ViewGroup extends ViewGroup {
    int custom_ViewGroup_height = 0;
    int child_Count = 0;
    float start_value = 0;
    float difference_value = 0;
    int pointer_ID = 0;
    float Y = 0;
    //横向滑动不处理字段
    float intercept_valueX = 0;
    float intercept_X = 0;
    float intercept_valueY = 0;
    float intercept_Y = 0;
    Scroller scroller = new Scroller(getContext());

    public custom_ViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int measure_child_count = getChildCount();
        for(int m = 0;m<measure_child_count;m++){
            View view = getChildAt(m);
            measureChild(view,widthMeasureSpec, heightMeasureSpec);
        }
    }
    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        custom_ViewGroup_height = getHeight();
        child_Count = getChildCount();
        MarginLayoutParams params = (MarginLayoutParams) getLayoutParams();
        params.height = child_Count * custom_ViewGroup_height;
        setLayoutParams(params);
        for (int a = 0; a < child_Count; a++) {
            View view = getChildAt(a);
            if (view.getVisibility() != View.GONE) {
                view.layout(i, a * custom_ViewGroup_height, i2, a * custom_ViewGroup_height + custom_ViewGroup_height);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return true;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        //横向滑动不做处理代码
        if (intercept_valueX > event.getX()) {
            intercept_X = intercept_valueX - event.getX();
        } else {
            intercept_X = event.getX() - intercept_valueX;
        }
        if (intercept_valueY > event.getY()) {
            intercept_Y = intercept_valueY - event.getY();
        } else {
            intercept_Y = event.getY() - intercept_valueY;
        }
        switch (MotionEventCompat.getActionMasked(event)) {
            case MotionEvent.ACTION_DOWN:
                //初始值
                intercept_valueX = event.getX();
                intercept_valueY = event.getY();

                start_value = event.getY();
                int index = event.getActionIndex();
                pointer_ID = MotionEventCompat.getPointerId(event, index);
                break;
            case MotionEvent.ACTION_UP:
                reset();
                break;
            case MotionEvent.ACTION_MOVE:
                int index_1 = MotionEventCompat.findPointerIndex(event, pointer_ID);
                Y = MotionEventCompat.getY(event, index_1);
                difference_value = start_value - Y;
                start_value = Y;
                //下滑或者上滑手势才会进入此判断
                if(intercept_X+3<intercept_Y) {
                    scrollBy(0, (int) difference_value);
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                down_Method(event);
                break;
            case MotionEvent.ACTION_POINTER_UP:
                up_Method(event);
                break;
            default:
                break;
        }
        //处理滑动过界情况
        if(getScrollY()<0){
            scrollTo(0,0);
        }
        if(getScrollY()>(child_Count-1)*custom_ViewGroup_height){
            scrollTo(0,(child_Count-1)*custom_ViewGroup_height);
        }
        return super.dispatchTouchEvent(event);
    }

    private void reset() {
        int mEnd = getScrollY();
        //属于当前页面的Y最大值
        int current_page_maxY ;
        //当前属于第几页
        int current_page = getScrollY()/custom_ViewGroup_height;
        current_page_maxY = current_page*custom_ViewGroup_height;
        int reset_value = mEnd - current_page_maxY;
        if(reset_value>0){
            if(reset_value<custom_ViewGroup_height/2){
                scroller.startScroll(0,getScrollY(),0,-reset_value,200);
            }else{
                scroller.startScroll(0,getScrollY(),0,custom_ViewGroup_height-reset_value,200);
            }
            postInvalidate();
        }else{
            if(-reset_value<custom_ViewGroup_height/2){
                scroller.startScroll(0,getScrollY(),0,-reset_value,200);
            }else{
                scroller.startScroll(0,getScrollY(),0,-custom_ViewGroup_height-reset_value,200);
            }
            postInvalidate();
        }
    }
    //处理手指离开事件,注意当屏幕上从两只手指以上的其中一只手指离开才会调用此方法
    private void up_Method(MotionEvent event) {
        int leave_index = MotionEventCompat.getActionIndex(event);
        int leave_pointerID = MotionEventCompat.getPointerId(event, leave_index);
        if (pointer_ID == leave_pointerID) {
            int newPointerIndex = leave_index == 0 ? 1 : 0;
            start_value = MotionEventCompat.getY(event,newPointerIndex);
            pointer_ID = MotionEventCompat.getPointerId(event,newPointerIndex);
        }
    }
    //处理手指按下事件,此时屏幕必须不少于两只手指
    private void down_Method(MotionEvent ev) {
        int index = MotionEventCompat.getActionIndex(ev);
        intercept_valueX = MotionEventCompat.getX(ev, index);
        intercept_valueY = start_value = MotionEventCompat.getY(ev, index);
        start_value = MotionEventCompat.getY(ev, index);
        pointer_ID = MotionEventCompat.getPointerId(ev, index);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if(scroller.computeScrollOffset()){
            scrollTo(0,scroller.getCurrY());
            postInvalidate();
        }
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值