TabLayout用自定义视图更新标签内容

我正在使用新的材料devise的TabLayout ,我有一个问题,一旦创build标签,我无法更新自定义视图的选项卡内容:

我可以用我的PagerAdapter简化我的方法

 public View setTabView(int position, boolean selected) { View v = LayoutInflater.from(context).inflate(R.layout.default_tab_view, null); tv = (TextView) v.findViewById(R.id.tabTextView); if(selected) tv.setText("SELECTED"); else tv.setText("UNSELECTED"); return v; } 

在活动中,我可以简化我的代码:

 TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); ViewPager pager = (ViewPager) findViewById(R.id.viewpager); PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager()); pager.setAdapter(adapter); tabLayout.setupWithViewPager(pager); for (int i = 0; i < tabLayout.getTabCount(); i++) { TabLayout.Tab tab = tabLayout.getTabAt(i); View v; if (i == 0) { v = adapter.setTabView(i, true); v.setSelected(true); } else v = adapter.setTabView(i, false); tab.setCustomView(v); } tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { adapter.setTabView(tab.getPosition(), true); } @Override public void onTabUnselected(TabLayout.Tab tab) { adapter.setTabView(tab.getPosition(), false); } @Override public void onTabReselected(TabLayout.Tab tab) { } }); 

标签的标题设置正确的应用程序启动时,但当我改变标签,内容仍然保持不变。

Solutions Collecting From Web of "TabLayout用自定义视图更新标签内容"

好吧, 我认为这是Androiddevise支持库v22上的错误。

因为你在谈论内容的变化,但是我不能改变文本的颜色。 一旦标签被创build,如果你改变布局,它不会反映。

正如我看到你的代码,你正在使用setCustomView自定义布局。 并且为了改变文本,你再次调用方法setTabView()。 而不是应该有方法getCustomView(),以便您可以更改布局。 在TabLayout.Tab.getCustomView中有一个方法,但它没有标识符,我已经报告了这个错误。

https://code.google.com/p/android/issues/detail?id=177492

[更新08-07-2015]

最后错误被android bug源码traking接受并标记为Future Release 。 所以我们可以说未来的图书馆将不再存在错误。 我们可以使用方法getCustomView()以便我们可以轻松地获得我们的自定义视图。

[更新18-08-2015]

最后这个bug解决了在v23支持库中发布 。 只需使用SDKpipe理器更新支持库,并将getCustomView()作为public。

在gradle中改变这一行

 compile 'com.android.support:design:23.0.0' 

并确保编译和目标sdk设置为23。

请检查我的代码为我工作正常

 TabLayout.Tab tab=tabLayout.getTabAt(position); View view=tab.getCustomView(); TextView txtCount= (TextView) view.findViewById(R.id.txtCount); txtCount.setText(count+""); 

好的,我可能会发现一个非常棘手的解决scheme,因为我没有时间去等待下一个支持库版本。 以下是我所做的:

  1. 将寻呼机适配器设置为您的TabLayout tabLayout.setTabsFromPagerAdapter(pagerAdapter);
  2. 将监听器添加到您的ViewPager

      customViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { tabLayout.getTabAt(position).select(); } @Override public void onPageScrollStateChanged(int state) { } }); 
  3. 将监听器添加到您的TabLayout

     tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { if (!isTabUpdating) { isTabUpdating = true; final int pos = tab.getPosition(); customViewPager.setCurrentItem(pos); // Clears and populates all tabs tabLayout.setTabsFromPagerAdapter(pagerAdapter); invalidateTabs(pos); } } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { if (!isTabUpdating) { isTabUpdating = true; final int pos = tab.getPosition(); customViewPager.setCurrentItem(pos); // Clears and populates all tabs tabLayout.setTabsFromPagerAdapter(pagerAdapter); invalidateTabs(pos); } } }); 
  4. 添加方法重新绘制所有选项卡

     private void invalidateTabs(int selected) { for (int i = 0; i < tabLayout.getTabCount(); i++) { tabLayout.getTabAt(i).setCustomView(pagerAdapter.getTabView(i, i == selected)); } isTabUpdating = false; } 

好的,让我解释一下。 首先,您可能想知道为什么我使用setTabsFromPagerAdapter()而不是setupWithViewPager 。 在开始我使用setupWithViewPager但不知何故我的传呼机无法正常工作,第一个项目不能被选中。

你可能会承认的第二件事 – 每次我select一个标签,我删除所有这些。 那么,这是一个容易的问题,当你调用Tab.setCustomView(View)时候,你会看到我的android源代码,它检查视图的父代,如果它不是null – 它将删除所有的childviews。 但是,如果您传递新实例化的项目,您将添加另一个视图,而不是replace旧的视图:

  View custom = tab.getCustomView(); if(custom != null) { ViewParent icon = custom.getParent(); if(icon != this) { if(icon != null) { // You wont get here ((ViewGroup)icon).removeView(custom); } this.addView(custom); } ... 

所以,我最终自己设置了所有的监听器,并且每次在页面/标签页更改时重新创build所有的标签页。 这不是一个好的解决scheme,但只要不能等到Google更新他们的lib,这可能是实现这种效果的唯一解决scheme。 (万一你想知道为什么这是如此复杂 – 我需要有自定义视图(文本+图像)的选项卡,可以改变他们的视图属性(字体颜色,图像),当他们被选中/取消select)

顺便说一句 – 这是第四步的getTabView(...)方法:

 public View getTabView(int pos, boolean isSeleted) { View tabview = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout .tab_sessioninfo, null, false); final ImageView ivTabIcon = (ImageView) tabview.findViewById(R.id.iv_tab_icon); final TextView tvTabTittle = (TextView) tabview.findViewById(R.id.tv_tab_title); if (isSeleted) { tvTabTittle.setTextColor(context.getResources().getColor(R.color.tab_indicator)); } switch (pos) { case 0: tvTabTittle.setText("1st Tab"); ivTabIcon.setImageResource(isSeleted ? R.drawable.ic_icon1_selected : R.drawable.ic_icon1); break; case 1: tvTabTittle.setText("2nd Tab"); ivTabIcon.setImageResource(isSeleted ? R.drawable.ic_icon2_selected : R.drawable.ic_icon2); break; case 2: tvTabTittle.setText("3rd Tab"); ivTabIcon.setImageResource(isSeleted ? R.drawable.ic_icon3_selected : R.drawable.ic_icon3); break; } return tabview; } 

PS如果你知道所有这些东西更好的解决scheme让我知道!

UPDATE

更好的解决scheme可以通过使用reflection来处理:

  1. 设置简单

     tabLayout.setupWithViewPager(customViewPager); customViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { for (int i = 0; i <tabLayout.getTabCount(); i++){ updateTab(tabLayout.getTabAt(i), position == i); } } @Override public void onPageScrollStateChanged(int state) { } }); 
  2. 更新标签

     private void updateTab(TabLayout.Tab tab, boolean isSelected){ Method method = null; try { method = TabLayout.Tab.class.getDeclaredMethod("getCustomView", null); method.setAccessible(true); View tabview = (View) method.invoke(tab, null); final ImageView ivTabIcon = (ImageView) tabview.findViewById(R.id.iv_tab_icon); final TextView tvTabTittle = (TextView) tabview.findViewById(R.id.tv_tab_title); if (isSeleted) { tvTabTittle.setTextColor(context.getResources().getColor(R.color.tab_indicator)); } switch (pos) { case 0: tvTabTittle.setText("1st Tab"); ivTabIcon.setImageResource(isSeleted ? R.drawable.ic_icon1_selected : R.drawable.ic_icon1); break; case 1: tvTabTittle.setText("2nd Tab"); ivTabIcon.setImageResource(isSeleted ? R.drawable.ic_icon2_selected : R.drawable.ic_icon2); break; case 2: tvTabTittle.setText("3rd Tab"); ivTabIcon.setImageResource(isSeleted ? R.drawable.ic_icon3_selected : R.drawable.ic_icon3); break; } tab.setCustomView(tabview); } catch (Exception e) { e.printStackTrace(); } } 

UPDATE

新的支持库有getCustomView()公共方法,所以你不需要reflection!

请检查我的代码为我工作正常

 TabLayout.Tab tab=tabLayout.getTabAt(position); View view=tab.getCustomView(); TextView txtCount= (TextView) view.findViewById(R.id.txtCount); txtCount.setText(count+""); 

看看你需要设置的布局按预期的布局。 如果要更改Tab内容,请在Tab.setOnTabSelectedListener()中进行更改

 tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { if(tab.getPosition()==1){ tabLayout.setTabTextColors(ContextCompat.getColor(getActivity(), R.color.unselected_tab),ContextCompat.getColor(getActivity(), R.color.tab_selection)); }else{ tabLayout.setTabTextColors(ContextCompat.getColor(getActivity(), R.color.unselected_tab),ContextCompat.getColor(getActivity(), R.color.white)); } // same thing goes with other tabs too // Just change your tab text on selected/deselected as above } @Override public void onTabUnselected(TabLayout.Tab tab) { tab.setCustomView(null); } @Override public void onTabReselected(TabLayout.Tab tab) { } });