Android ViewPager 和 TabPageIndicator 的限制滑动和禁用点击

前两天做一个项目的时候,有这么个需求,如下图:

Android ViewPager 和 TabPageIndicator 的限制滑动和禁用点击_第1张图片

整个实现用的是TabPageIndicator + ViewPager ,现在的要求是上面的TabPageIndicator 和 下面的 ViewPager 都要能根据相应的数据做到TabPageIndicator限制是否可以点击(只限制点击,要保持能滑动)以及ViewPager是否可以滑动。(蛋疼的需求)

首先看到这个问题的时候,第一想到的时候看源码有没有提供类似的处理机制,很遗憾,我没有找到。

那看来只能自己来实现了,首先是TabPageIndicator,一开始看到它有个setEnable()方法,以为这么简单就搞定了,结果才发现其实是然并卵。其实这个方法是因为它继承了HorizontalScrollView 带过来的方法,真正是不起作用的。

既然简单的实现不了,那就只能,拿出本办法了,查看源码再做相应的修改了。

在查看源码的过程中,我主要看到有这么两个方法:

private void addTab(int index, CharSequence text, int iconResId) {
        final TabView tabView = new TabView(getContext());
        tabView.mIndex = index;
        tabView.setFocusable(true);
        tabView.setOnClickListener(mTabClickListener);
        tabView.setText(text);

        if (iconResId != 0) {
            tabView.setCompoundDrawablesWithIntrinsicBounds(iconResId, 0, 0, 0);
        }

        mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, MATCH_PARENT, 1));
    }

可以看到在这里,它对每一个tabView进行了相应的设置,并监听了点击事件。然后是接下来的这个重点方法了:

@Override
    public void setCurrentItem(int item) {
        if (mViewPager == null) {
            throw new IllegalStateException("ViewPager has not been bound.");
        }
        mSelectedTabIndex = item;
        mViewPager.setCurrentItem(item);

        final int tabCount = mTabLayout.getChildCount();
        for (int i = 0; i < tabCount; i++) {
            final View child = mTabLayout.getChildAt(i);
            final boolean isSelected = (i == item);
            child.setSelected(isSelected);
            if (isSelected) {
                animateToTab(item);
            }
        }
    }

可以看到它重写了ViewPager的setCurrentItem()方法。我想看到这一步的时候,小伙伴们是否已经明白了?在这里我们要实现的代码片段就出来了。

 public void setTabViewState(int max){
        final int tabCount = mTabLayout.getChildCount();
        for (int i = 0; i < tabCount; i++) {
            final View child = mTabLayout.getChildAt(i);
            if (i <= max) {
                child.setEnabled(true) ;
            } else {
                child.setEnabled(false) ;
            }
        }
    }

看吧,这就是我抽取出来的公共方法,如法炮制有木有。一个循环,一个限制,搞定。

好吧,既然TabPageIndicator已经搞定了,那么剩下的就是ViewPager了,一开始觉得这块应该也很简单,但实际上却花了些时间。

为了避免重复制造轮子,我先去伟大的百毒上搜了一圈,发现也有人遇到过需要限制ViewPager滑动的问题,顿时眼前一亮,索嘎,顿时觉得会上网真是件极好的事情。but…..,一个个试了之后发现限制是可以限制了,但是跟我项目的需求有出入,又一个然而并没有什么卵用!!

好吧,既然不符合,那我就自己在这个基础改改总行了吧,嗯,想到就开始行动。折腾来折腾去,发现还是不行,总是差那么一点。看来这最后一步才真的是决定性的一大步啊!

好,正逢抗战70周年,就好好发挥下我们劳动人民的一不怕苦,二不怕累的勤劳精神吧。

接下来可得来点干货了,不然要被打了估计。
在解决这个问题之前我们很有必要搞清楚Android 上的Touch 事件分发机制。在这里非常感谢sunzn’Blog博主的这篇文章,地址是:点击跳转

在了解了Touch事件分发机制后,我决定重写onTouchEvent()方法,具体原因就不说了,相信你们看了上面那篇文章已经明了。(ps:我会告诉你其实我也不知道,哈哈,尼玛,坑爹有木有!!)

首先说下思路,我觉得这个远远比之前提供源码要好得多,在这之前呢,我查看了ViewPager的源码实现,具体请自行百毒查看。或者你可以查看这篇博文:点击跳转。发现ViewPager的滑动也是处理Touch事件。那就简单了,我只需要在点击滑动的时候,首先判断是左滑还是右滑,然后在相应的地方处理下自己的业务逻辑,做出下判断,如果达到设定的限制,就拦截事件,否则就不处理。好了,有了理论基础,就要开始实践了。

代码如下:

package com.viewpagerindicator.sample.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

public class CustomViewPager extends ViewPager {
    private int maxLimit = 0 ;
    private float start = 0 ;

    public int getMaxLimit() {
        return maxLimit;
    }

    public void setMaxLimit(int maxLimit) {
        this.maxLimit = maxLimit;
    }

    public CustomViewPager(Context context) {
        super(context);
    }

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

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN :
            start = event.getX() ;
            Log.i("CustomViewPager", "start==--> "+start);
            break;
        case MotionEvent.ACTION_MOVE :
            float med = event.getX() ;
            int difference = (int) (med - start) ;
            Log.i("CustomViewPager", "med==--> "+med+",difference--->"+difference);
            if (difference > 0) { // 右滑, 页面向左
                Log.i("CustomViewPager", "右滑");
            } else if (difference < 0) {
                Log.i("CustomViewPager", "左滑");
                int item = getCurrentItem() + 1 ;
                if (item > maxLimit) {
                    Log.i("CustomViewPager", "maxLimit");
                    return true ;
                }
            }
            break ;
        case MotionEvent.ACTION_UP :
            float end = event.getX() ;
            Log.i("CustomViewPager", "end==--> "+end);
            break ;
        default:
            break;
        }
        return super.onTouchEvent(event) ;
    }
}

代码未做清理,弄好了,赶紧跑一下,是骡子是马得拉出来溜溜才知道,一跑,大功告成!(运行结果看最开始的图。)YEAR,nice!今天真是个好日子,BTW,今天我生日,在这个好日子里,没别的啥庆祝的,特此记录下这个功能,希望能帮助到有需要的朋友。(ps:唉,由于本人不怎么写博客,技术也一般,请各位看官留情,小弟感激涕零!)

在文章最后,我会把整个工程上传。
ps:由于第一次上传的资源文件,代码被加密了,因此重新上传一份未加密的。对之前下载过的兄弟说句抱歉了。
下载地址

你可能感兴趣的:(Android学习笔记)