Вопрос по android-design-library, tabs, android – TabLayout обновить содержимое вкладки с настраиваемым представлением

24

я использую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++) {
    boolean isFirstTab = i == 0;
    TabLayout.Tab tab = tabLayout.getTabAt(i);
    View v;
    v = adapter.setTabView(i, isFirstTab);
    v.setSelected(isFirstTab);
    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) {

    }
});

Заголовки вкладок устанавливаются правильно при запуске приложения, но когда я меняю вкладку, содержимое остается прежним.

Ваш Ответ

4   ответа
45

ХорошоЯ думаю, что это ошибка в библиотеке поддержки дизайна Android 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 , Просто обновите библиотеку поддержки, используя менеджер SDK, и вы получите getCustomView () в качестве общедоступного.

просто измените эту строку в Gradle

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

и убедитесь, что для compile и target sdk установлено значение 23.

пожалуйста, проверьте мой код работает нормально для меня

TabLayout.Tab tab=tabLayout.getTabAt(position);         
View view=tab.getCustomView();         
TextView txtCount= (TextView) 
view.findViewById(R.id.txtCount);         
txtCount.setText(count+"");
Вы проверили это правильно ... они показывают 23.0.1 .... со списком ошибок, которые устранены .. Moinkhan
Смотри сюдаdeveloper.android.com/tools/support-library/index.html Moinkhan
Хорошо, я понимаю, что вы говорите, но в конце концов ошибка принята и решена Google. Теперь статус этой ошибки - будущий выпуск. Таким образом, нам не нужно делать какие-либо хитрые решения .. Moinkhan
Отлично, я пойду за этим. Giorgio Antonioli
0

пожалуйста, проверьте мой код работает нормально для меня

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

ПосмотритеОтветВы должны установить макет, как вы ожидаете. Если вы хотите изменить содержимое вкладки, внесите изменения в 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) {

    }
});
7

Ну ладно, я мог бы найти очень хитрое решение только потому, что у меня не было времени ждать следующей версии библиотеки поддержки. Вот что я сделал:

Установите адаптер пейджера на ваш TabLayouttabLayout.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) он проверяет родителя представления и, если он не нулевой, удаляет все дочерние представления. Однако, если вы передадите только что созданный элемент, вы добавите другой вид вместо того, чтобы заменить старый:

    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 не может дождаться обновления своей библиотеки - это, вероятно, единственное решение для достижения такого эффекта.(На случай, если вам интересно, почему это так сложно - мне нужно было иметь вкладки с пользовательскими представлениями (текст + изображение), которые могли бы изменять их свойства вида (цвет шрифта, изображение), когда они выбраны / не выбраны)

Кстати - вот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;
}

Постскриптум Если вы знаете лучшее решение для всего этого, дайте мне знать!

ОБНОВИТЬ

Лучшее решение может быть достигнуто с помощью отражения:

Простая настройка

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

ОБНОВИТЬ

Новая библиотека поддержки имеет публичный метод дляgetCustomView()так что вам больше не нужно отражение!

У меня нет макета для вкладки, я просто использовал библиотеку. так как я могу связать компонент "final ImageView ivTabIcon = (ImageView) tabview.findViewById (R.id.iv_tab_icon);", где мне нужно добавить пользовательский макет? Tara
@ Тара, не могли бы вы объяснить, чего вы пытаетесь достичь? Paul Freez
Я использую прямую библиотеку, не определяя никакой пользовательский макет для вкладки. Как вы определили «R.layout.tab_sessioninfo». Если я не использую какой-либо пользовательский макет, то у меня не будет никакого ImageView. Моя повестка дня была при нажатии на вкладку, что значок вкладки меняется. Что-то вроде того, что до выбора вкладки, ее значок был серым, а после выбора значок менялся на синий. Как бы то ни было, я решил свою проблему, добавив методы "addOnPageChangeListener и onPageSelected". Tara

Похожие вопросы