2016-03-21 9 views
0

動的なタブの追加と削除オプションを使用してアプリケーションを作成したいのですが、問題が1つあります。onCreateViewは常にviewPagerAdapter.addTab()の後に呼び出されるとは限りません

初めてタブを追加するときはすべて問題ありませんが、1つのタブを削除して新しいタブをもう一度追加したい場合、その新しいフラグメントに対してonCreateViewが呼び出されません。

例:onCreateViewが呼び出され

ViewPagerAdapter vpa = (ViewPagerAdapter) mViewPager.getAdapter(); 
vpa.addTab("TAB 1"); 
vpa.notifyDataSetChanged(); 

  • タブ1を追加します。

    私は、新しい3つのタブが追加されます。

    some logs: 
        [add tab] mViewPager.getChildCount() = 1 
        [add tab] vpa.getCount() = 1 
    
    • タブ2追加:onCreateViewが呼び出され
    vpa.addTab("TAB 2"); 
    vpa.notifyDataSetChanged(); 
    

    を。

    some logs: 
        [add tab] mViewPager.getChildCount() = 2 
        [add tab] vpa.getCount() = 2 
    
    • タブ3追加:onCreateViewが呼び出され
    vpa.addTab("TAB 3"); 
    vpa.notifyDataSetChanged(); 
    

    を。

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

2番目のフラグメント(削除/追加後)にスワイプするとどうなりますか? – Yazan

+0

その後、そのフラグメントにスワイプしますが、そのフラグメントで同じアイテムをrecyclerViewに追加したい場合は、アプリケーションクラッシュ(NullPointerException)が発生します。 onCreateViewが呼び出されなかったため、そのフラグメントのオブジェクトは初期化されません。 – NeyroN

答えて

1

[OK]を、私はその問題を解決します。

の削除:

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

} 

ご挨拶!

関連する問題