How to scroll tablayout programmatically - Android

前端 未结 13 2132
终归单人心
终归单人心 2021-02-07 00:31

I have created 30 scrollable tabs using tablayout.

So first three tabs are visible on screen and rest of them are invisible which can be scroll using swipe gesture.

相关标签:
13条回答
  • 2021-02-07 00:36

    To select the last tab, use tabLayout.getTabAt(X).select(); where X is the last tab index

    0 讨论(0)
  • 2021-02-07 00:38

    The above answer wouldn't work because first As agirardello mentioned you should not use mTabLayout.getWidth() since it doesn't return what we need (which is the position of the child you want to scroll to) and the updated solution doesn't always work because of a bug in TabLayout (reported here) but a work around is simple.

    The tabs on the tabLayout are not direct children of the TabLayout so we need to go one level deeper using

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

    the only child of tabLayout is a TabLayout.SlidingTabStrip which is also a ViewGroup and getRight() will give us the right most position of our desired tab view. Thus scrolling to that position will give us what we desire. Here is a complete code:

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

    NOTE: Make sure you are calling these methods after the layout has been drown (like onResume and not onCreate)

    Hope this helps.

    0 讨论(0)
  • 2021-02-07 00:44

    This solution worked for me. My situation is a little bit different though; in my case, I am using the TabLayout with a ViewPager and adding more views and calling notifyDataSetChange().

    The solution is to set a callback on the observer of TabLayout and scroll when the children are actually added to the TabLayout. Here is my example:

    /**
        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;
                }
            }
        });
    }
    

    Here is my code for the PagerAdapter if you need it too 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;
        }
    }
    
    0 讨论(0)
  • 2021-02-07 00:45

    The code snippet below works for me

    class TriggerOnceListener(private val v: View, private val block: () -> Unit) : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            block()
            v.viewTreeObserver.removeOnPreDrawListener(this)
            return true
        }
    }
    
    fun onCreate() {
        val position = ***The tab position you want to scroll to, 29 for your case here***
        tabLayout.let { it.viewTreeObserver.addOnPreDrawListener(TriggerOnceListener(it)
        { it.setScrollPosition(position, 0f, true) } ) }
    }
    

    I dived into Tab.select(), and found Android uses Tablayout.setScrollPosition() to do this scrolling. And in onCreate() the widgets have not been measured, you need to postpone the call until layout is complete.

    0 讨论(0)
  • 2021-02-07 00:46
    tab = tabLayout.getSelectedTabPosition();
                tab++;
                TabLayout.Tab tabs = tabLayout.getTabAt(tab);
                if (tabs != null) {
                    tabs.select();
                }
                else {
                    tabLayout.getTabAt(0).select();
                }
    

    if you want next tab on click event then use this code its work perfactly

    0 讨论(0)
  • 2021-02-07 00:48

    write this method in your custom tablayout (Your own layout which extends tablayout). So, in future you can use this method whenever you need instad of code duplication

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

    If you don't want yo use CustomLayout. you can just do this

    final Tab currentTab = mTabLayout.getTabAt(tabIndex);
    if(currentTab != null){
         mTabLayout.post(new Runnable() {
                        @Override
                        public void run() {
                            currentTab.select();
                        }
                    });
    }
    
    0 讨论(0)
提交回复
热议问题