TabLayout обновляет содержимое вкладки с настраиваемым представлением
Я использую TabLayout
нового дизайна материалов, и у меня есть проблема, я не могу обновить содержимое вкладки пользовательского представления после создания вкладки:
Я могу упростить свой метод внутри своего 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) {
}
});
Заголовки вкладок устанавливаются правильно, когда приложение запускается, но когда я меняю вкладку, содержимое остается неизменным.
Ответы
Ответ 1
Хорошо Я думаю, что это ошибка в библиотеке поддержки дизайна vroid v22.
Потому что вы говорите об изменениях в содержании, но я не могу изменить цвет текста. Как только вкладка будет создана, и если вы измените макет, он не будет отображаться.
И Поскольку я видел ваш код, вы предоставляете настраиваемый макет с помощью setCustomView. и для изменения текста вы снова вызываете метод setTabView(). Вместо этого должен быть метод getCustomView(), чтобы вы могли изменить макет. Существует метод в TabLayout.Tab.getCustomView, но у него нет идентификатора, и я сообщаю об этой ошибке.
https://code.google.com/p/android/issues/detail?id=177492
[Обновить 08-07-2015]
Наконец, ошибка принимается трафиком источника ошибок Android и помечена как Будущая версия. Таким образом, мы можем сказать, что ошибка будет больше не существовать в будущей библиотеке.
и мы можем иметь метод getCustomView()
, чтобы мы могли легко получить наш пользовательский вид.
[Обновить 18-08-2015]
Наконец, ошибка решена. Выпущена в v23 support libs.
Просто обновите библиотеку поддержки, используя диспетчер SDK, и у вас есть getCustomView() как общедоступный.
просто измените эту строку в 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+"");
Ответ 2
Хорошо, я мог найти очень сложное решение только потому, что у меня не было времени ждать следующей версии поддержки-библиотеки. Вот что я сделал:
- Установите адаптер пейджера на вкладку TabLayout
tabLayout.setTabsFromPagerAdapter(pagerAdapter);
-
Добавить прослушиватель в 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) {
}
});
-
Добавить слушателя на вкладку 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);
}
}
});
-
Добавить метод повторного рисования всех вкладок
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
, но почему-то это не сработало правильно с моим пейджером, и 1-й элемент не был выбран.
Второе, что вы можете признать - каждый раз, когда я выбираю вкладку, я удаляю все из них. Ну, это была легкая проблема, вы видите, что я источник Android, когда вы вызываете Tab.setCustomView(View)
, он проверяет родителя представления и, если он не равен null, он удаляет все дочерние объекты. Однако, если вы передаете новый экземпляр объекта, вы добавите другой вид вместо замены старого:
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);
}
...
Итак, я закончил настройку всех слушателей самостоятельно и каждый раз создавал все вкладки на странице/вкладке. Это НЕ хорошее решение, но, поскольку он не может дождаться, когда Google обновит их lib - это, вероятно, единственное решение для достижения такого эффекта. (На всякий случай вам интересно, почему это так сложно - мне нужно было иметь вкладки с пользовательскими представлениями (текст + изображение), которые могли бы изменить их свойства вида (цвет шрифта, изображение), когда они будут выбраны/не выбраны)
BTW - здесь метод getTabView(...)
с 4-го шага:
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;
}
P.S. Если вы знаете лучшее решение для всего этого, дайте мне знать!
UPDATE
К лучшему решению можно подойти с помощью Reflection:
-
Простая настройка
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) {
}
});
-
Обновить вкладку
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()
, поэтому вам больше не нужно размышлять!
Ответ 3
пожалуйста, проверьте, что мой код работает нормально для меня
TabLayout.Tab tab=tabLayout.getTabAt(position);
View view=tab.getCustomView();
TextView txtCount= (TextView) view.findViewById(R.id.txtCount);
txtCount.setText(count+"");
Ответ 4
Посмотрите Ответ, вам нужно установить макет, как и ожидалось. Если вы хотите изменить содержимое вкладки, внесите изменения в 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) {
}
});