Как прокрутить tablayout программно – Android

Я создал 30 прокручиваемых вкладок, используя tablayout.

Таким образом, первые три вкладки видны на экране, а остальные из них невидимы, которые можно прокручивать с помощью жестов салфетки.

Проблема в том, что я выбираю последнюю вкладку программно, но она не становится видимой (вкладка не прокручивается до последней вкладки).

Как заставить tablayout прокручиваться до последней вкладки?

Заранее спасибо.

Solutions Collecting From Web of "Как прокрутить tablayout программно – Android"

Я нашел решение.

Сначала я нашел ширину tablayout и прокрутил ее по оси x до ширины, а затем вызвал метод select () последней вкладки.

И он отлично работает.

Ниже приведен код.

mTabLayout.setScrollX(mTabLayout.getWidth()); mTabLayout.getTabAt(lastTabIndex).select(); 

Обновлено :

Если выше не работает, вы также можете использовать приведенный ниже код, он также работает нормально.

 new Handler().postDelayed( new Runnable() { @Override public void run() { mTabLayout.getTabAt(TAB_NUMBER).select(); } }, 100); 

Я нашел это решение для меня:

  TabLayout tabLayout = activity.getTabLayout(); tabLayout.setSmoothScrollingEnabled(true); tabLayout.setScrollPosition(targetChannelPosition, 0f, true); 

Кроме того, если вы получите эту ошибку: «Только исходный поток, создавший иерархию представлений, может коснуться его представлений». Вы можете использовать этот код для запуска в потоке Ui:

  // find a way to get the activity containing the tab layout TabLayout tabLayout = activity.getTabLayout(); activity.runOnUiThread(new Runnable() { @Override public void run() { TabLayout.Tab tab = tabLayout.getTabAt(targetChannelPosition); tab.select(); } }); 

Вышеупомянутый ответ не сработает, потому что сначала, как сказал агирдардо, вы не должны использовать mTabLayout.getWidth() поскольку он не возвращает то, что нам нужно (которое является положением дочернего элемента, который вы хотите прокрутить), а обновленное решение не использует, T всегда работает из-за ошибки в TabLayout (см. Здесь ), но простая работа.

Вкладки tabLayout не являются прямыми дочерними элементами TabLayout, поэтому нам нужно идти на один уровень глубже, используя

 ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(YOUR_DESIRED_TAB_INDEX).getRight() 

Единственным дочерним элементом tabLayout является TabLayout.SlidingTabStrip который также является ViewGroup и getRight() предоставит нам право самой позиции нашего желаемого вида вкладок. Таким образом, прокрутка к этой позиции даст нам то, что мы желаем. Вот полный код:

 int right = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(4).getRight(); mTabLayout.scrollTo(right,0); mTabLayout.getTabAt(4).select(); 

ПРИМЕЧАНИЕ. Убедитесь, что вы вызываете эти методы после того, как макет утонул (например, onResume, а не onCreate)

Надеюсь это поможет.

Напишите этот метод в своем пользовательском tablayout (ваш собственный макет, который расширяет tablayout). Таким образом, в будущем вы можете использовать этот метод всякий раз, когда вам нужна инстанция дублирования кода

 public void selectTabAt(int tabIndex) { if (tabIndex >= 0 && tabIndex < getTabCount() && getSelectedTabPosition() != tabIndex) { final Tab currentTab = getTabAt(tabIndex); if (currentTab != null) { this.post(new Runnable() { @Override public void run() { currentTab.select(); } }); } } } 

Если вы не хотите, чтобы вы использовали CustomLayout. Вы можете просто сделать это

 final Tab currentTab = mTabLayout.getTabAt(tabIndex); if(currentTab != null){ mTabLayout.post(new Runnable() { @Override public void run() { currentTab.select(); } }); } 

Чтобы выбрать последнюю вкладку, используйте tabLayout.getTabAt (X) .select (); Где X – последний индекс вкладки

Вы вызываете tab.select() перед TabLayout, и его дети фактически были измерены и нарисованы? Если это так, ваш TabLayout не будет анимировать выделение с помощью tab.select() (или предложения scrollTo() N scrollTo() ). Использование обработчика, вероятно, будет работать, но это не идеальное решение.

Если макет еще не был выложен, ViewTreeObserver позволит вам перейти на выбранную вкладку после завершения процесса компоновки.

 private void scrollToTabAfterLayout(final int tabIndex) { if (getView() != null) { final ViewTreeObserver observer = mTabLayout.getViewTreeObserver(); if (observer.isAlive()) { observer.dispatchOnGlobalLayout(); // In case a previous call is waiting when this call is made observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { observer.removeOnGlobalLayoutListener(this); } else { //noinspection deprecation observer.removeGlobalOnLayoutListener(this); } mTabLayout.getTabAt(tabIndex).select(); } }); } } } 

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

viewpager.setItem(position) также должен установить положение вкладки

Это решение сработало для меня. Моя ситуация немного отличается; В моем случае я использую TabLayout с ViewPager и добавляю больше просмотров и вызываю notifyDataSetChange ().

Решение состоит в том, чтобы установить обратный вызов наблюдателя TabLayout и прокручивать, когда дети фактически добавлены в TabLayout. Вот мой пример:

 /** Keep in mind this is how I set my TabLayout up... PagerAdapter pagerAdapter = new PagerAdapter(...); ViewPager pager = (ViewPager)findViewById(...); pager.setAdapter(pagerAdapter); TabLayout tabLayout = (TabLayout)findViewById(...); tabLayout.setupWithViewPager(pager); */ public void loadTabs(String[] topics) { animateTabsOpen(); // Irrelevant to solution // Removes fragments from ViewPager pagerAdapter.clear(); // Adds new fragments to ViewPager for (String t : topics) pagerAdapter.append(t, new TestFragment()); // Since we need observer callback to still animate tabs when we // scroll, it is essential to keep track of the state. Declare this // as a global variable scrollToFirst = true; // Alerts ViewPager data has been changed pagerAdapter.notifyOnDataSetChanged(); // Scroll to the beginning (or any position you need) in TabLayout // using its observer callbacks tabs.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { /** We use onGlobalLayout() callback because anytime a tab is added or removed the TabLayout triggers this; therefore, we use it to scroll to the desired position we want. In my case I wanted to scroll to the beginning position, but this can easily be modified to scroll to any position. */ if (scrollToFirst) { tabs.getTabAt(0).select(); tabs.scrollTo(0, 0); scrollToFirst = false; } } }); } 

Вот мой код для PagerAdapter, если вам это нужно слишком lol:

 public class PagerAdapter extends FragmentStatePagerAdapter { private List<Fragment> fragments; private List<String> titles; public PagerAdapter(FragmentManager fm) { super(fm); this.fragments = new ArrayList<>(); this.titles = new ArrayList<>(); } /** * Adds an adapter item (title and fragment) and * doesn't notify that data has changed. * * NOTE: Remember to call notifyDataSetChanged()! * @param title Fragment title * @param frag Fragment * @return This */ public PagerAdapter append(String title, Fragment frag) { this.titles.add(title); this.fragments.add(frag); return this; } /** * Clears all adapter items and doesn't notify that data * has changed. * * NOTE: Rememeber to call notifyDataSetChanged()! * @return This */ public PagerAdapter clear() { this.titles.clear(); this.fragments.clear(); return this; } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public CharSequence getPageTitle(int position) { return titles.get(position); } @Override public int getCount() { return fragments.size(); } @Override public int getItemPosition(Object object) { int position = fragments.indexOf(object); return (position >= 0) ? position : POSITION_NONE; } } 
 new Handler().postDelayed( new Runnable() { @Override public void run() { mTabLayout.getTabAt(TAB_NUMBER).select(); } }, 100); 

Интересно, будет ли это ответ уместным, так как его приход очень поздний. Я действительно добился этого в C #, используя Xamarin.

 tabs.GetChildAt(0).Selected = true; viewPager.SetCurrentItem(0, true); 

Если ваш TabLayout используется совместно с ViewPager , который является общим, просто добавьте следующее в метод onCreate() в своей деятельности:

 tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager); viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout); 

Что некоторые из ваших вкладок не отображаются, указывает, что для атрибута tabMode установлено app:tabMode="scrollable" .