Android底部Tab页基于ViewPager的实现

在众多主流App中,包括QQ,微信等,为了和ios的UI保持统一,很多App使用的都是底部导航,当然在Android中也并不反对这种设计。这篇文章使用ViewPager实现这种效果。首先看实现效果图吧。效果图中包含了ViewPager的嵌套。

这里写图片描述

这里写图片描述

在讨论实现之前,我们先来回忆一下,之前我们是如何实现的。

之前的实现方法,我们无法是先进行布局,再编写逻辑。而布局,底部有一定高度的Tab,一般由4个或者5个,也有3个的,具体视应用而定,而Tab上方则是一个FrameLayout,用于作为fragment的容器。在Activity中处理对应的点击事件的逻辑,需要自己控制Fragment的显示与隐藏,有时候控制不好甚至会带来莫名其妙的问题。

那么有没有一种简单的方法,避免我们自己编写Fragment切换的逻辑呢,其实是有的,ViewPager正是这个控件,这时候有人问了,一般放在底部的导航内容区域是点击切换的,不会滑动切换(微信除外),ViewPager是会滑动切换的,那么怎么解决这个问题呢。答案是重写ViewPager,提供一个布尔变量,用于控制是否支持滑动切换,通过这个变量,对对应事件的函数onTouchEvent和onInterceptTouchEvent进行重写,如果该变量设置为true,即支持滑动切换,也就是ViewPager的默认行为,我们使用父类的方法进行处理。如果是false,我们不进行处理或者不进行拦截,返回false即可。这样,我们的ViewPager子类的代码就成了这样。

public class CustomViewPager extends ViewPager {
    private boolean isCanScroll = false;

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

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

    public boolean isCanScroll() {
        return isCanScroll;
    }

    public void setCanScroll(boolean isCanScroll) {
        this.isCanScroll = isCanScroll;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (isCanScroll) {
            return super.onTouchEvent(ev);
        } else {
            return false;
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (isCanScroll) {
            return super.onInterceptTouchEvent(ev);
        } else {
            return false;
        }
    }
}

使用我们自己的ViewPager代替默认的ViewPager进行布局就可以了,如下

    <com.kltz.tabdemo.view.CustomViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >
    </com.kltz.tabdemo.view.CustomViewPager>

然后我们简单进行底部Tab的布局

<RadioGroup
        android:id="@+id/radio"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#e8e8e8"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/tab1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/btn"
            android:button="@drawable/btn"
            android:gravity="center"
            android:text="Tab1"
            />

        <RadioButton
            android:id="@+id/tab2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/btn"
            android:button="@null"
            android:gravity="center"
            android:text="Tab2"
            />

        <RadioButton
            android:id="@+id/tab3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/btn"
            android:button="@null"
            android:gravity="center"
            android:text="Tab3"
            />

        <RadioButton
            android:id="@+id/tab4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/btn"
            android:button="@null"
            android:gravity="center"
            android:text="Tab4"
            />
    </RadioGroup>

上面两段布局外围是一个线性布局,使用了layout_weight属性控制了内容区域的高度。

然后Tab按钮的点击是有效果的,编写我们的Selector作为按钮的背景,这里随便选了两个颜色,实际开发中用对应图片代替。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:drawable="@color/accent_material_light"/>
    <item android:drawable="@color/abc_search_url_text_normal"/>
</selector>

最后来看看我们简单的逻辑处理,对RadioGroup设置监听,当点击了之后判断是哪一个Button,将ViewPager显示为对应的页,使用setCurrentItem函数,第二个参数传false,代表无切换动画。

public class MainActivity extends AppCompatActivity{
    private CustomViewPager mViewPager;
    private RadioGroup mRadioGroup;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mViewPager= (CustomViewPager) findViewById(R.id.viewpager);
        mRadioGroup= (RadioGroup) findViewById(R.id.radio);
        mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int i) {
                return BaseFragment.newInstance(i);
            }

            @Override
            public int getCount() {
                return 4;
            }
        });
        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.tab1:
                        mViewPager.setCurrentItem(0, false);
                        break;
                    case R.id.tab2:
                        mViewPager.setCurrentItem(1, false);
                        break;
                    case R.id.tab3:
                        mViewPager.setCurrentItem(2, false);
                        break;
                    case R.id.tab4:
                        mViewPager.setCurrentItem(3, false);
                        break;
                }
            }
        });
    }

}

很简单的Tab实现有木有,有时候系统有的组件,我们需要的功能如果与其相似,可以改造一下直接拿来用,没必要重复造轮子。

源码下载

http://download.csdn.net/detail/sbsujjbcy/8881617

如果你觉得对你有帮助,点个赞吧!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值