2016-03-21 10 views
0

Ich möchte App mit dynamischen hinzufügen/entfernen Tabs Option erstellen und ich habe Probleme mit einer Sache.onCreateView wird nicht immer nach viewPagerAdapter.addTab() aufgerufen

Wenn ich zum ersten Mal Tabs hinzufüge, ist alles in Ordnung, aber wenn ich einen Tab entferne und ich einen neuen Tab hinzufügen möchte, dann gibt es kein onCreateView, das dieses neue Fragment aufgerufen hat.

Beispiel:

ich hinzufügen neue 3 Registerkarten:

  • hinzufügen Tab 1:
ViewPagerAdapter vpa = (ViewPagerAdapter) mViewPager.getAdapter(); 
vpa.addTab("TAB 1"); 
vpa.notifyDataSetChanged(); 

onCreateView genannt wird.

some logs: 
    [add tab] mViewPager.getChildCount() = 1 
    [add tab] vpa.getCount() = 1 
  • hinzufügen Tab 2:
vpa.addTab("TAB 2"); 
vpa.notifyDataSetChanged(); 

onCreateView genannt wird.

some logs: 
    [add tab] mViewPager.getChildCount() = 2 
    [add tab] vpa.getCount() = 2 
  • hinzufügen Tab 3:
vpa.addTab("TAB 3"); 
vpa.notifyDataSetChanged(); 

onCreateView genannt wird.

some logs: 
    [add tab] mViewPager.getChildCount() = 3 
    [add tab] vpa.getCount() = 3 
  • jetzt will ich Tab 2 löschen:
vpa.removeTab("TAB 2"); 
vpa.notifyDataSetChanged(); 
some logs: 
    [add tab] mViewPager.getChildCount() = 2 
    [add tab] vpa.getCount() = 2 
  • und ich möchte wieder hinzufügen 2 Tab:
vpa.addTab("TAB 2"); 
vpa.notifyDataSetChanged(); 

und es gibt keine onCreateView genannt :(

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

Kann jemand wissen, wie das beheben? Warum wird onCreateView nicht immer aufgerufen?

App Code:

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); 
    } 
} 
+0

Was passiert, wenn Sie zum zweiten Fragment wischen (nach dem Entfernen/Hinzufügen)? – Yazan

+0

App wischen dann zu diesem Fragment, aber wenn ich dasselbe Element zu recyclerView in diesem Fragment dann App crash (NullPointerException) hinzufügen möchten. Objekte dieses Fragments werden nicht initialisiert, da onCreateView nicht aufgerufen wurde. – NeyroN

Antwort

1

Ok, ich dieses Problem beheben.

Löschen:

mViewPager.setOffscreenPageLimit(10); 

Aufschalten Methoden Fragmente Zustand zu speichern:

public void onViewStateRestored(@Nullable Bundle savedInstanceState) 

public void onSaveInstanceState(Bundle outState) 

Und ich habe meine eigene FragmentStatePagerAdapter Klasse erstellt. Ich musste den Fragmentstatus nicht auf der Registerkarte speichern, die gelöscht wurde.

Code:

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); 
    } 

} 

Grüße!