在viewPagerAdapter.addTab()

时间:2016-03-21 09:19:17

标签: android android-fragments tabs android-viewpager swipe

我想用动态添加/删除标签选项创建应用程序,我有一件事有问题。

当我第一次添加标签时一切正常但是当我删除一个标签并且我想再次添加新标签时,没有onCreateView调用该新片段。

示例:

我添加了新的3个标签:

  • 添加标签1:
ViewPagerAdapter vpa = (ViewPagerAdapter) mViewPager.getAdapter();
vpa.addTab("TAB 1");
vpa.notifyDataSetChanged();
调用

onCreateView。

some logs:
    [add tab] mViewPager.getChildCount() = 1
    [add tab] vpa.getCount() = 1
  • 添加标签2:
vpa.addTab("TAB 2");
vpa.notifyDataSetChanged();
调用

onCreateView。

some logs:
    [add tab] mViewPager.getChildCount() = 2
    [add tab] vpa.getCount() = 2
  • 添加标签3:
vpa.addTab("TAB 3");
vpa.notifyDataSetChanged();
调用

onCreateView。

some logs:
    [add tab] mViewPager.getChildCount() = 3
    [add tab] vpa.getCount() = 3
  • 现在我要删除标签2:
vpa.removeTab("TAB 2");
vpa.notifyDataSetChanged();
some logs:
    [add tab] mViewPager.getChildCount() = 2
    [add tab] vpa.getCount() = 2
  • 我想再次添加标签2:
vpa.addTab("TAB 2");
vpa.notifyDataSetChanged();

并且没有onCreateView被称为:(

some logs:
    [add tab] mViewPager.getChildCount() = 2
    [add tab] vpa.getCount() = 3

任何人都知道如何解决这个问题吗?为什么不总是调用onCreateView?

应用代码:

private void initViewpagerAndTabs(){
    mViewPager = (ViewPager) findViewById(R.id.viewpager_slave);
    mViewPager.setOffscreenPageLimit(10);
    mAdapterViewPager = new ViewPagerAdapter(getSupportFragmentManager());
    mViewPager.setAdapter(mAdapterViewPager);
    mTabLayout = (TabLayout) findViewById(R.id.tabLayout_slave);
    mTabLayout.setupWithViewPager(mViewPager);
}
/** Tabs content fragment */
public static class DummyFragment extends Fragment implements RecyclerAdapter.ViewHolder.ClickListener {
    private RecyclerView mRecyclerView;
    private RecyclerAdapter mAdapterRecycler;
    private RecyclerView.LayoutManager mLayoutManager;
    private Fab fab;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.content_slave, container, false);

        //setRetainInstance(true);
        initRecyclerView(view);
        fab = (Fab) getActivity().findViewById(R.id.fabRemoveItems);

        return view;
    }

    private void initRecyclerView(View view){
        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_slave);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        mLayoutManager = new LinearLayoutManager(getContext());
        mRecyclerView.setLayoutManager(mLayoutManager);
        RecyclerView.ItemAnimator itemAnimator = mRecyclerView.getItemAnimator();
        itemAnimator.setAddDuration(500);
        itemAnimator.setRemoveDuration(500);

        mAdapterRecycler = new RecyclerAdapter(this);
        mRecyclerView.setAdapter(mAdapterRecycler);
    }

}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private final List<DummyFragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    public DummyFragment getItem(int num) throws IndexOutOfBoundsException{
        return mFragmentList.get(num);
    }

    public void addTab(String title) throws Exception {
        if(isTabExist(title)){
            throw new Exception("Tabs already exist!");
        }
        //Log.d(TAG, "[addTab] mFragmentTitleList before add: " + mFragmentTitleList);
        //Log.d(TAG, "[addTab] mFragmentList before add: " + mFragmentList);
        mFragmentList.add(new DummyFragment());
        mFragmentTitleList.add(title);
        //Log.d(TAG, "[addTab] mFragmentTitleList after add: " + mFragmentTitleList);
        //Log.d(TAG, "[addTab] mFragmentList after add: " + mFragmentList);
    }

    public void removeTab(int position){
        //Log.d(TAG, "[removeTab] mFragmentTitleList before removed: " + mFragmentTitleList);
        //Log.d(TAG, "[removeTab] mFragmentList before removed: " + mFragmentList);
        mFragmentTitleList.remove(position);
        mFragmentList.remove(position);
        //Log.d(TAG, "[removeTab] mFragmentTitleList after removed: " + mFragmentTitleList);
        //Log.d(TAG, "[removeTab] mFragmentList after removed: " + mFragmentList);
    }

    private boolean isTabExist(String name){
        for(int i = 0; i < mFragmentTitleList.size(); i++) {
            if (mFragmentTitleList.get(i).equals(name)) {
                return true;
            }
        }
        return false;
    }

    public int getTabPosition(String tabName) throws IndexOutOfBoundsException{
        for(int i = 0; i < mFragmentTitleList.size(); i++) {
            if (mFragmentTitleList.get(i).equals(tabName)) {
                return i;
            }
        }
        throw new IndexOutOfBoundsException();
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
      getSupportFragmentManager().beginTransaction().remove((Fragment) object)
                .commit();
    }

    @Override
    public int getItemPosition(Object object) {
        if (mFragmentList.contains(object)) return mFragmentList.indexOf(object);
        else return POSITION_NONE;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

1 个答案:

答案 0 :(得分:1)

好的,我解决了这个问题。

删除:

mViewPager.setOffscreenPageLimit(10);

覆盖保存片段状态的方法:

public void onViewStateRestored(@Nullable Bundle savedInstanceState)

public void onSaveInstanceState(Bundle outState)

我已经创建了自己的FragmentStatePagerAdapter类。我不需要在已删除的标签上保存片段状态。

代码:

public class FragStatePagerAdaper extends PagerAdapter {

    private static final String TAG = "FragStatePagerAdapter";
    private static final boolean DEBUG = true;

    private final FragmentManager mFragmentManager;
    private FragmentTransaction mCurTransaction = null;

    private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
    /** Cached fragments */
    private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
    private Fragment mCurrentPrimaryItem = null;

    private List<DummyFragment> mFragmentList = new ArrayList<>();
    private List<String> mFragmentTitleList = new ArrayList<>();

    public FragStatePagerAdaper(FragmentManager fm) {
        mFragmentManager = fm;
    }

    /**
     * Return the Fragment associated with a specified position.
     */
    public DummyFragment getItem(int num) throws IndexOutOfBoundsException{
        return mFragmentList.get(num);
    }

    @Override
    public void startUpdate(ViewGroup container) {
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // If we already have this item instantiated, there is nothing
        // to do.  This can happen when we are restoring the entire pager
        // from its saved state, where the fragment manager has already
        // taken care of restoring the fragments we previously had instantiated.
        if (mFragments.size() > position) {
            Fragment f = mFragments.get(position);
            if (f != null) {
                return f;
            }
        }

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        Fragment fragment = getItem(position);
        if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
        if (mSavedState.size() > position) {
            Fragment.SavedState fss = mSavedState.get(position);
            if (fss != null) {
                fragment.setInitialSavedState(fss);
            }
        }
        while (mFragments.size() <= position) {
            mFragments.add(null);
        }
        fragment.setMenuVisibility(false);
        fragment.setUserVisibleHint(false);
        mFragments.set(position, fragment);
        mCurTransaction.add(container.getId(), fragment);

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        while (mSavedState.size() <= position) {
            mSavedState.add(null);
        }

        mSavedState.set(position, fragment.isAdded()
                    ? mFragmentManager.saveFragmentInstanceState(fragment) : null);

        mFragments.set(position, null);

        mCurTransaction.remove(fragment);
    }

    public void addTab(String title) throws Exception {
        if(isTabExist(title)){
            throw new Exception("Tabs already exist!");
        }
        mFragmentList.add(new DummyFragment());
        mFragmentTitleList.add(title);
    }

    //look here!
    public void removeTab(int position){
        Log.d(TAG, "removeTab: position = " + position);
        mFragmentTitleList.remove(position);
        mFragmentList.remove(position);
        mSavedState.remove(position);  // <---- here!
    }

    private boolean isTabExist(String name){
        for(int i = 0; i < mFragmentTitleList.size(); i++) {
            if (mFragmentTitleList.get(i).equals(name)) {
                return true;
            }
        }
        return false;
    }

    public int getTabPosition(String tabName) throws IndexOutOfBoundsException{
        for(int i = 0; i < mFragmentTitleList.size(); i++) {
            if (mFragmentTitleList.get(i).equals(tabName)) {
                return i;
            }
        }
        throw new IndexOutOfBoundsException();
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment)object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                mCurrentPrimaryItem.setUserVisibleHint(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
                fragment.setUserVisibleHint(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }

    @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }

        ArrayList<Fragment> update = new ArrayList<Fragment>();
        for (int i=0, n=mFragments.size(); i < n; i++) {
            Fragment f = mFragments.get(i);
            if (f == null) continue;
            int pos = getItemPosition(f);
            while (update.size() <= pos) {
                update.add(null);
            }
            update.set(pos, f);
        }
        mFragments = update;
    }


    @Override
    public boolean isViewFromObject(View view, Object object) {
        return ((Fragment)object).getView() == view;
    }

    @Override
    public Parcelable saveState() {
        Bundle state = null;
        if (mSavedState.size() > 0) {
            state = new Bundle();
            Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
            mSavedState.toArray(fss);
            state.putParcelableArray("states", fss);
        }
        for (int i=0; i<mFragments.size(); i++) {
            Fragment f = mFragments.get(i);
            if (f != null && f.isAdded()) {
                if (state == null) {
                    state = new Bundle();
                }
                String key = "f" + i;
                mFragmentManager.putFragment(state, key, f);
            }
        }
        return state;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        if (state != null) {
            Bundle bundle = (Bundle)state;
            bundle.setClassLoader(loader);
            Parcelable[] fss = bundle.getParcelableArray("states");
            mSavedState.clear();
            mFragments.clear();
            if (fss != null) {
                for (int i=0; i<fss.length; i++) {
                    mSavedState.add((Fragment.SavedState)fss[i]);
                }
            }
            Iterable<String> keys = bundle.keySet();
            for (String key: keys) {
                if (key.startsWith("f")) {
                    int index = Integer.parseInt(key.substring(1));
                    Fragment f = mFragmentManager.getFragment(bundle, key);
                    if (f != null) {
                        while (mFragments.size() <= index) {
                            mFragments.add(null);
                        }
                        f.setMenuVisibility(false);
                        mFragments.set(index, f);
                    } else {
                        Log.w(TAG, "Bad fragment at key " + key);
                    }
                }
            }
        }
    }

    @Override
    public int getItemPosition(Object object) {
        if (mFragmentList.contains(object)) return mFragmentList.indexOf(object);
        else return POSITION_NONE;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }

}

<强>问候!