23

Ho un TabLayout e all'interno ho ViewPager. Devo aggiungere e rimuovere dinamicamente la scheda in tablayout (design del materiale). Posso aggiungere le schede in modo dinamico ma rimuovendo la scheda, la scheda viene rimossa correttamente. Ma l'ultimo elemento di viewpager è stato cancellato. Quindi la scheda non mostra il frammento specifico. Per tua informazione ho usato FragmentPagerAdapter.Aggiunge e rimuove dinamicamente le schede in TabLayout (material design) android

Ho seguito questo tutorial per implementare questo

https://androidbelieve.com/navigation-drawer-with-swipe-tabs-using-design-support-library

public class TabFragment extends Fragment { 

    public static TabLayout tabLayout; 
    public static ViewPager viewPager; 
    public static int int_items = 2; 
    private MyNewsFragment mMyNewsFragment; 
    private ArrayList<TabFragmentModelClass> mFragmentArrayList; 
    private TabLayoutAdapter mTabLayoutAdapter; 

    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     mMyNewsFragment = new MyNewsFragment(); 
     /** 
     *Inflate tab_layout and setup Views.i;;a 
     */ 
     View x = inflater.inflate(R.layout.tab_layout, null); 
     tabLayout = (TabLayout) x.findViewById(R.id.tabs); 
     tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE); // scorllable tab 
     tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); // tab name fill parent 
     viewPager = (ViewPager) x.findViewById(R.id.viewpager); 
     mFragmentArrayList = new ArrayList<>(); 
     mFragmentArrayList.add(new TabFragmentModelClass(new MyNewsSelectionFragment(), "", "")); 
     mFragmentArrayList.add(new TabFragmentModelClass(mMyNewsFragment, "", getResources().getString(R.string.mynews))); 
     mFragmentArrayList.add(new TabFragmentModelClass(new BreakingNewsFragment(), "", getResources().getString(R.string.breakingnews))); 

     // Selected news from shared preference 
     ArrayList<MyNewsSharedPreferenceModelClass> tempSharedPreferenceModelClass = new MyNewsSharedPreferenceClass().loadFavorites(getActivity()); 
     for (int i = 0; i < tempSharedPreferenceModelClass.size(); i++) { 
      mFragmentArrayList.add(new TabFragmentModelClass(new CategoreyNewsFragment(tempSharedPreferenceModelClass.get(i).getmCatID()), tempSharedPreferenceModelClass.get(i).getmCatID(), 
        tempSharedPreferenceModelClass.get(i).getmCatName())); 
     } 


} 


     /** 
     *Set an Apater for the View Pager 
     */ 
     mTabLayoutAdapter = new TabLayoutAdapter(getChildFragmentManager(), mFragmentArrayList); 
     viewPager.setAdapter(mTabLayoutAdapter); 
     viewPager.setOffscreenPageLimit(mFragmentArrayList.size()); 
     tabLayout.setupWithViewPager(viewPager); 


     viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
      @Override 
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
      } 

      @Override 
      public void onPageSelected(int position) { 
       tabLayout.getTabAt(position); 
      } 

      @Override 
      public void onPageScrollStateChanged(int state) { 
       if (state == 1) { 
        updateMyNewsFragment(); 
       } 
      } 
     }); 

     /** 
     * Now , this is a workaround , 
     * The setupWithViewPager dose't works without the runnable . 
     * Maybe a Support Library Bug . 
     */ 

     tabLayout.post(new Runnable() { 
      @Override 
      public void run() { 

       tabLayout.getTabAt(0).setIcon(R.mipmap.mynewselection); 

       tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { 
        @Override 
        public void onTabSelected(TabLayout.Tab tab) { 
         viewPager.setCurrentItem(tab.getPosition()); 
         switch (tab.getPosition()) { 
          case 1: 

           System.out.println("000000000000000000000 "); 
           updateMyNewsFragment(); 
           break; 
         } 
        } 

        @Override 
        public void onTabUnselected(TabLayout.Tab tab) { 
        } 


        @Override 
        public void onTabReselected(TabLayout.Tab tab) { 
        } 
       }); 

      } 
     }); 
     return x; 
    } 

    /** 
    * update the mynews selection 
    * this method trigger from the MainNewsActivity 
    */ 
    public void updateMyNewsFragment() { 
     if (ApplicationController.getInstance().getBoolPref(CommonVariableInterFace.isNewsSelected)) { 
      mMyNewsFragment.sendMyNewsRequest(); 
      ApplicationController.getInstance().setBoolPref(CommonVariableInterFace.isNewsSelected, false); 
     } 
    } 

    /** 
    * update the tab values 
    * this method trigger from the MainNewsActivity 
    * if value is zero need to add in tab 
    * if value is one need to remove in tab 
    */ 
    public void updateTabvalue(String catId, String catName, int value) { 

      if (value == 0) { // add the value in tab 

       mFragmentArrayList.add(new TabFragmentModelClass(new CategoreyNewsFragment(catId), catId, 
         catName)); 
      } else {  // Removing the tab 
       for (int i = 0; i < mFragmentArrayList.size(); i++) { 
        if (mFragmentArrayList.get(i).getmCatID().equalsIgnoreCase(catId)) { 

         Log.i("-----same id ", catId); 
         mFragmentArrayList.remove(i); 
         mTabLayoutAdapter = new TabLayoutAdapter(getChildFragmentManager(), mFragmentArrayList); 
         viewPager.setAdapter(mTabLayoutAdapter); 
        } 
       } 
      } 

      mTabLayoutAdapter.notifyDataSetChanged(); 
      viewPager.setOffscreenPageLimit(mFragmentArrayList.size()); 
      tabLayout.getTabAt(0).setIcon(R.mipmap.mynewselection); 
      tabLayout.setupWithViewPager(viewPager); 


      tabLayout.post(new Runnable() { 
       @Override 
       public void run() { 

        tabLayout.getTabAt(0).setIcon(R.mipmap.mynewselection); 

        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { 
         @Override 
         public void onTabSelected(TabLayout.Tab tab) { 
          viewPager.setCurrentItem(tab.getPosition()); 
          switch (tab.getPosition()) { 
           case 1: 
            updateMyNewsFragment(); 
            break; 
          } 
         } 

         @Override 
         public void onTabUnselected(TabLayout.Tab tab) { 
         } 


         @Override 
         public void onTabReselected(TabLayout.Tab tab) { 
         } 
        }); 

       } 
      }); 
    } 

    public void openSpecificTab() { 

//  tabLayout.settab 
//  tabLayout.se 
    } 
} 

codice Adapter:

public class TabLayoutAdapter extends FragmentPagerAdapter { 

    private long baseId = 0; 
    ArrayList<TabFragmentModelClass> fragmentAdapterArrayList; 

    public TabLayoutAdapter(FragmentManager fm, ArrayList<TabFragmentModelClass> fragmentArrayList) { 
     super(fm); 
     fragmentAdapterArrayList = fragmentArrayList; 
    } 

    @Override 
    public Fragment getItem(int position) { 

     if (position == 0) 
      return fragmentAdapterArrayList.get(position).getmFragment(); 
     if (position == 1) 
      return fragmentAdapterArrayList.get(position).getmFragment(); 
     if (position == 2) 
      return fragmentAdapterArrayList.get(position).getmFragment(); 

     return new CategoreyNewsFragment().newInstance(fragmentAdapterArrayList.get(position).getmCatID()); 
    } 

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


    //this is called when notifyDataSetChanged() is called 
    @Override 
    public int getItemPosition(Object object) { 
     // refresh all fragments when data set changed 
     return TabLayoutAdapter.POSITION_NONE; 
    } 


    @Override 
    public long getItemId(int position) { 
     // give an ID different from position when position has been changed 
     return baseId + position; 
    } 

    /** 
    * Notify that the position of a fragment has been changed. 
    * Create a new ID for each position to force recreation of the fragment 
    * 
    * @param n number of items which have been changed 
    */ 
    public void notifyChangeInPosition(int n) { 
     // shift the ID returned by getItemId outside the range of all previous fragments 
     baseId += getCount() + n; 
    } 

    /** 
    * //  * This method returns the title of the tab according to the position. 
    * // 
    */ 

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

risposta

22

scheda Eliminare dal TabLayout

... 
public void removeTab(int position) { 
    if (mTabLayout.getTabCount() >= 1 && position<mTabLayout.getTabCount()) { 
      mTabLayout.removeTabAt(position); 
      mPagerAdapter.removeTabPage(position); 
    } 
} 
... 

aggiungere un metodo removeTabPage al PagerAdapter

... 
public void removeTabPage(int position) { 
    if (!tabItems.isEmpty() && position<tabItems.size()) { 
      tabItems.remove(position); 
      notifyDataSetChanged(); 
    } 
} 
... 

Aggiungi un Tab

... 
private void addTab(String title) { 
     mTabLayout.addTab(mTabLayout.newTab().setText(title)); 
     mPagerAdapter.addTabPage(title); 
} 
... 

aggiungere un metodo addTabPage al PagerAdapter

... 
public void addTabPage(String title) { 
     tabItems.add(title); 
     notifyDataSetChanged(); 
} 
... 

Dai un'occhiata a questo codice di esempio per una completa esempio: ...samples/SupportDesignDemos/src/com/example/android/support/design/widget/TabLayoutUsage.java

+0

Grazie tizio che era utile – Ruban

+1

ho provato quanto sopra, ma non l'ha fatto lavora per me. Dopo aver chiamato removeTab (2) su un viewpager con 5 frammenti ottengo l'errore java.lang.NullPointerException: tentativo di invocare il metodo virtuale 'int android.view.View.getLeft()' su un oggetto null reference @Ruban – Zvi

+1

@Zvi questo errore sembra che tu stia cercando di chiamare View.getLeft() su una vista che non è presente, prova e scopri perché? la chiamata a removeTab (2) ha rimosso il riferimento a questa vista? – TouchBoarder

10

Con la nuova libreria di supporto (sto usando 23.2.1) si dovrebbe solo aggiungere al Viewpager e non al TabLayout (altrimenti si finisce con doppie schede e altri comportamenti funky). Quindi, per aggiornare TouchBoarder's answer:

aggiungere un metodo removeTabPage al PagerAdapter

public void removeTabPage(int position) { 
    if (!tabItems.isEmpty() && position<tabItems.size()) { 
      tabItems.remove(position); 
      notifyDataSetChanged(); 
    } 
} 

aggiungere un metodo addTabPage al PagerAdapter

public void addTabPage(String title) { 
     tabItems.add(title); 
     notifyDataSetChanged(); 
} 
+0

Grazie Midas ... – Ruban

+0

cosa succede se non ho un adattatore di pagina? b layout? –