Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> viewPager+Fragment的多重嵌套問題

viewPager+Fragment的多重嵌套問題

編輯:關於Android編程

大多數場景下,會單單使用viewPager+Fragment來完成項目需求,但也有一些特殊情況需要用到viewPager的多重嵌套。

一、例如:

這裡寫圖片描述
我的想法是:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> ①用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代碼:




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

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




    

    

注:為方便日後理解,這裡貼出部分關鍵(小框架)代碼:

/**
 * @創建者 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 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();
            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];
        }
    }

}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved