viewPager+Fragment的多重嵌套问题

大多数场景下,会单单使用viewPager+Fragment来完成项目需求,但也有一些特殊情况需要用到viewPager的多重嵌套。

一、例如:

这里写图片描述
我的想法是:

①用viewPager+Fragment来完成"外卖、食堂、云购订单"这整个大的框架,到这里一切顺利。
②接着,用viewPager+Fragment来实现“外卖订单”里的“等配送、待付款、已完成、已取消”这整个小的框架,但这里在就出问题了。

二、“症状”:

①小框架的滑动事件出现了问题,不能流畅的从一个tab没到下一个tab
②每个tab中的内容是不显示的
③当滑动到“已完成”这个tab时,小框架被滑出去了,直接切换到大框架中的“食堂订单”
④到了“云购订单”时反而出现了小框架其中一个tab的内容

三、尝试:

我猜想这是2个viewPager嵌套产生的问题,于是自定义了小框架的viewPager,重写dispatchTouchEvent使父控件不拦截滑动事件,经测试,失败。自定义小框架的viewPager代码如下:

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

/**
 * @创建者 CSDN_LQR
 * @描述 自定义ViewPager:首尾页面父控件拦截事件
 */
public class CustomViewPager extends ViewPager {

    private int startX;
    private int startY;

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

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

    /**
     * 事件分发,请求父控件及祖宗控件是否拦截事件
     * 1、右划,而且是第一个页面,需要父控件拦截
     * 2、左划,而且是最后一个页面,需要父控件拦截
     * 3、上下滑动,需要父控件拦截
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);//不要拦截,这样是为了保证ACTION_MOVE调用

                startX = (int) ev.getRawX();
                startY = (int) ev.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:

                int endX = (int) ev.getRawX();
                int endY = (int) ev.getRawY();

                if (Math.abs(endX - startX) > Math.abs(endY - startY)) {//左右滑动
                    if (endX > startX) {//往右滑动
                        if (getCurrentItem() == 0) {//第一个页面,需要父控件拦截
                            getParent().requestDisallowInterceptTouchEvent(false);
                        }
                    } else {//左划
                        if (getCurrentItem() == getAdapter().getCount() - 1) {//最后一个页面,需要拦截
                            getParent().requestDisallowInterceptTouchEvent(false);
                        }
                    }
                } else {//上下滑动
                    getParent().requestDisallowInterceptTouchEvent(false);
                }

                break;

            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

}

四、原因:

经过一番折腾,原因还是未知,但是可以确定跟Fragment有关。

五、解决办法:

直接去掉Fragment!!!

1、自定义BasePager类:

①BasePager类代码:

import android.app.Activity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.dfdz.wmpt.R;

/**
 * @创建者 CSDN_LQR
 * @描述 基本页面(用于替换Fragment)
 */
public abstract class BasePager {

    public Activity mActivity;
    public View mRootView;//布局对象

    public TextView tvTitle;//标题对象

    public FrameLayout flContent;//内容

    public BasePager(Activity activity) {
        mActivity = activity;
        init();
    }

    private void init() {
        mRootView = View.inflate(mActivity, R.layout.base_pager, null);
        flContent = (FrameLayout) mRootView.findViewById(R.id.fl_content);
        flContent.addView(initView());
    }

    /**
     * 初始化布局
     */
    public abstract View initView();

    /**
     * 初始化数据
     */
    public void initData() {

    }

}

②base_pager.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <FrameLayout
        android:id="@+id/fl_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </FrameLayout>

</LinearLayout>
2、把之前小框架中的Fragment全部不继承Fragment,改继承BasePager(我这里不管大框架还是小框架全部继承BasePager)。
3、设置新的适配器

不使用FragmentPagerAdapter,使用PagerAdapter

    /**
     * @创建者 CSDN_LQR
     * @描述 viewPager的页面适配器
     */
    class ContentAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return mPagerList.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {

            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            BasePager pager = mPagerList.get(position);
            container.addView(pager.mRootView);
            pager.initData();//初始化数据。。。。不要放在此处初始化数据,否则会预加载下一个页面
            return pager.mRootView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mTlTitleArr[position];
        }
    }
4、布局中使用了上面的自定义ViewPager
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/tlTop"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        app:tabBackground="@color/white"
        app:tabIndicatorColor="@color/main_bg3"
        app:tabIndicatorHeight="1dp"
        app:tabSelectedTextColor="@color/main_bg3"
        app:tabTextAppearance="@style/TabLayoutTextStyle"
        app:tabTextColor="@color/text0"/>

    <com.dfdz.wmpt.view.CustomViewPager
        android:id="@+id/vpContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

注:为方便日后理解,这里贴出部分关键(小框架)代码:

/**
 * @创建者 CSDN_LQR
 * @描述 OrderFragment中的外卖订单pager
 */
public class TakeOutFoodOrderPager extends BasePager {

    @InjectView(R.id.tlTop)
    TabLayout mTlTop;
    @InjectView(R.id.vpContent)
    CustomViewPager mVpContent;

    private String[] mTlTitleArr;
    private List<BasePager> mPagerList;
    private ContentAdapter mMyPagerAdapter;

    public TakeOutFoodOrderPager(Activity activity) {
        super(activity);
    }


    @Override
    public View initView() {
        View view = View.inflate(mActivity, R.layout.fragment_takeoutfood_cateen, null);
        ButterKnife.inject(this, view);
        //设置tabLayout模式
        mTlTop.setTabMode(TabLayout.MODE_FIXED);
        return view;
    }

    @Override
    public void initData() {
        mTlTitleArr = UIUtils.getStringArr(R.array.tablayout_title_takeoutfood);
        if (mPagerList == null) {
            mPagerList = new ArrayList<BasePager>();
            mPagerList.add(new WaitDistributionTakeOutFoodPager(mActivity));
            mPagerList.add(new WaitPayTakeOutFoodPager(mActivity));
            mPagerList.add(new FinishTakeOutFoodPager(mActivity));
            mPagerList.add(new CancelTakeOutFoodPager(mActivity));
        }
        //添加Tab
        for (String title : mTlTitleArr) {
            mTlTop.addTab(mTlTop.newTab().setText(title));
        }
        //设置viewPager页面适配器
        mMyPagerAdapter = new ContentAdapter();
        mVpContent.setAdapter(mMyPagerAdapter);
        //关联tabLayout和viewPager
        mTlTop.setupWithViewPager(mVpContent);
    }

    /**
     * @创建者 CSDN_LQR
     * @描述 viewPager的页面适配器
     */
    class ContentAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return mPagerList.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {

            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            BasePager pager = mPagerList.get(position);
            container.addView(pager.mRootView);
            pager.initData();//初始化数据。。。。不要放在此处初始化数据,否则会预加载下一个页面
            return pager.mRootView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mTlTitleArr[position];
        }
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值