在TabLayout(材料设计)android中动态添加和删除标签

Posted

技术标签:

【中文标题】在TabLayout(材料设计)android中动态添加和删除标签【英文标题】:Dynamically add and remove tabs in TabLayout(material design) android 【发布时间】:2016-03-22 06:17:15 【问题描述】:

我有一个 TabLayout,里面有 ViewPager。我需要在标签布局(材料设计)中动态添加和删除标签。我可以动态添加选项卡,但是在删除选项卡时,选项卡正在正确删除。但是viewpager最后一项被删除了。所以选项卡没有显示特定的片段。仅供参考,我使用了 FragmentPagerAdapter。

我已经按照这个教程来实现这个

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
    

适配器代码:

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

【问题讨论】:

【参考方案1】:

TabLayout删除标签

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

...

removeTabPage 方法添加到您的PagerAdapter

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

...

添加Tab

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

...

addTabPage 方法添加到您的PagerAdapter

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

...

查看此示例代码以获取完整示例:...samples/SupportDesignDemos/src/com/example/android/support/design/widget/TabLayoutUsage.java

【讨论】:

谢谢老兄,很有用 我尝试了上述方法,但它对我不起作用。在带有 5 个片段的 viewpager 上调用 removeTab(2) 后,我收到错误 java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getLeft()' on an null object reference @Ruban @Zvi 这个错误看起来像你试图在不存在的视图上调用 View.getLeft() ,试着找出原因?对 removeTab(2) 的调用是否删除了对该视图的引用? 我解决了这个问题。我从 onTabSelected() 中调用 removeTab()。一旦我将其移至活动的主代码,问题就消失了。谢谢 使用 FragmentStatePagerAdapter 而不是 FragmentPagerAdapter 解决的问题【参考方案2】:

使用新的支持库(我使用的是 23.2.1),您应该只添加到 Viewpager 而不是 TabLayout(否则您最终会出现双标签和其他时髦的行为)。所以要更新TouchBoarder's answer:

将 removeTabPage 方法添加到您的 PagerAdapter

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

向您的 PagerAdapter 添加一个 addTabPage 方法

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

【讨论】:

如果我没有页面适配器怎么办?并且只有标签布局? @ZulqurnainJutt:我认为你可以这样做 TabLayout.Tab tab = tabLayout.newTab().setText("General"); tabLayout.addTab(tab);【参考方案3】:

除了现有答案之外,从 tabLayout 中删除所有选项卡。

tabLayout.removeAllTabs();

【讨论】:

【参考方案4】:

您可以像这样添加动态标签:

 public void addTabs()
    for(YourClassModel tabName: tabsName)
        Log.i("ActivityClass","tabName"+tabName);
        tabLayout.addTab(tabLayout.newTab().setText(tabName.getName()));

    

【讨论】:

【参考方案5】:

从标签布局中移除标签

TabActivity 和 ViewPager 代码:

`public class ScrollableTabsActivity extends AppCompatActivity

int NumberOfTab = 5;
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
ViewPagerAdapter adapter ;
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_scrollable_tabs);

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    adapter = new ViewPagerAdapter(getSupportFragmentManager());
    viewPager = (ViewPager) findViewById(R.id.viewpager);
    setupViewPager(viewPager);

    tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);

    int length = tabLayout.getTabCount();

    for (int i = 0; i < length; i++) 
        tabLayout.getTabAt(i).setCustomView(getTabView(i));
    



public View getTabView(final int position) 
    View view = LayoutInflater.from(this).inflate(R.layout.close_tablayout, null);
    TextView title = (TextView) view.findViewById(R.id.title);
    ImageView icon = (ImageView) view.findViewById(R.id.close);
    title.setText(adapter.getPageTitle(position));
    icon.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            NumberOfTab = NumberOfTab - 1;
            setupViewPager(viewPager);
            tabLayout.setupWithViewPager(viewPager);
            if (tabLayout.getTabCount()==3)
                tabLayout.setTabMode(TabLayout.MODE_FIXED);

            int length = tabLayout.getTabCount();
            for (int i = 0; i < length; i++) 
                tabLayout.getTabAt(i).setCustomView(getTabView(i));
            


        
    );

    return view;


private void setupViewPager(ViewPager viewPager) 
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(adapter);


class ViewPagerAdapter extends FragmentPagerAdapter 

    public ViewPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int position) 
        final Fragment result;
        switch (position) 
            case 0:
                // First Fragment of First Tab
                result = new OneFragment();
                break;
            case 1:
                // First Fragment of Second Tab
                result = new TwoFragment();
                break;
            case 2:
                // First Fragment of Second Tab
                result = new ThreeFragment();
                break;
            case 3:
                // First Fragment of Second Tab
                result = new FourFragment();
                break;

            case 4:
                // First Fragment of Second Tab
                result = new FiveFragment();
                break;

            default:
                result = null;
                break;
        

        // Log.d("RESULT",result.getTag());
        return result;
    

    @Override
    public int getCount() 
        return NumberOfTab;
    

    @Override
    public CharSequence getPageTitle(final int position) 
        switch (position) 
            case 0:
                return "One";
            case 1:
                return "Two";
            case 2:
                return "Three";
            case 3:
                return "Four";
            case 4:
                return "Five";
            default:
                return null;
        
    


`

查看此链接: https://***.com/a/58480151/9223264

我是***的新手,如果您认为我的回答有用,我会尽力而为,请欣赏

【讨论】:

以上是关于在TabLayout(材料设计)android中动态添加和删除标签的主要内容,如果未能解决你的问题,请参考以下文章

Android Material Design 史上最全的材料设计控件大全

android 指示器 tablatyout

android设计TabLayout标签的文字大小

在android设计支持TabLayout中更改标签文本的字体

TabLayout(Android 设计库)文本颜色

Android TabLayout Android 设计