在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 史上最全的材料设计控件大全