web-dev-qa-db-fra.com

Comment faire défiler tablayout par programme - Android

J'ai créé 30 onglets déroulants en utilisant tablayout.

Ainsi, les trois premiers onglets sont visibles à l'écran et les autres sont invisibles. Vous pouvez les faire défiler en faisant glisser le curseur.

Le problème est que je sélectionne le dernier onglet par programme, mais que cela ne soit pas visible (la disposition des onglets ne soit pas défilée jusqu'au dernier onglet).

Comment puis-je faire tablayout pour faire défiler jusqu'au dernier onglet?

17
Mohit Charadva

J'ai trouvé la solution.

Premièrement, j'avais trouvé la largeur de tablayout et fait défiler sa position x en largeur et ensuite appelé la méthode select () du dernier onglet.

Et ça marche bien.

Ci-dessous le code.

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

Mis à jour :

Si ci-dessus ne fonctionne pas, vous pouvez également utiliser le code ci-dessous, il fonctionne également très bien.

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

J'ai trouvé cette solution pour moi:

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

En outre, si vous recevez cette erreur: "Seul le thread d'origine qui a créé une hiérarchie de vues peut toucher ses vues.", Vous pouvez utiliser ce code pour s'exécuter sur le thread 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();
        }
    });
5
sunlover3

écrivez cette méthode dans votre tablayout personnalisé (votre propre mise en page qui étend tablayout). Ainsi, à l'avenir, vous pourrez utiliser cette méthode chaque fois que vous aurez besoin d'un instad de duplication de code.

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

Si vous ne voulez pas utiliser CustomLayout. tu peux juste faire ça

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

La réponse ci-dessus ne fonctionnerait pas car, comme le disait d'abord Agardardello, vous ne devriez pas utiliser mTabLayout.getWidth() car il ne renvoie pas ce dont nous avons besoin (la position de l'enfant que vous souhaitez faire défiler) et la solution mise à jour ne fonctionne pas toujours d'un bug dans TabLayout (rapporté ici ) mais un travail est simple.

Les onglets de tabLayout ne sont pas des enfants directs de TabLayout, nous devons donc aller plus loin en utilisant: 

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

le seul enfant de tabLayout est un TabLayout.SlidingTabStrip qui est également un ViewGroup et getRight() nous donnera la position la plus à droite de la vue en onglet souhaitée. Ainsi, le défilement jusqu'à cette position nous donnera ce que nous désirons. Voici un code complet:

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

REMARQUE: assurez-vous d'appeler ces méthodes une fois que la mise en page s'est noyée (comme onResume et non onCreate).

J'espère que cela t'aides.

2
Kayvan N

Pour sélectionner le dernier onglet, utilisez TabLayout.getTabAt (X) .select (); où X est le dernier index de tabulation

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

Appelez-vous tab.select() avant que TabLayout et ses enfants aient été réellement mesurés et dessinés? Si tel est le cas, votre TabLayout n'animera pas la sélection avec tab.select() (ou la suggestion de Kayvan N de scrollTo()). L'utilisation d'un gestionnaire fonctionnera probablement, mais ce n'est pas la solution idéale.

Si la disposition n'a pas encore été mise en page, un ViewTreeObserver vous permettra de passer à l'onglet sélectionné une fois le processus de mise en page terminé.

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

                }
            });
        }
    }
}

Veuillez commenter si vous avez des suggestions.

1
Matthew Sisinni
tab = tabLayout.getSelectedTabPosition();
            tab++;
            TabLayout.Tab tabs = tabLayout.getTabAt(tab);
            if (tabs != null) {
                tabs.select();
            }
            else {
                tabLayout.getTabAt(0).select();
            }

_ {si vous voulez le prochain onglet sur l'événement click, utilisez ce code parfaitement

0
RanaUmer

Je me demande si cette réponse sera pertinente puisqu'elle arrive très tard. En fait, je l’ai atteint en C # avec Xamarin.

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

viewpager.setItem(position) devrait également définir la position de la tabulation

0
locomain

Cette solution a fonctionné pour moi. Ma situation est un peu différente cependant; dans mon cas, j'utilise TabLayout avec un ViewPager, j'ajoute plus de vues et j'appelle notifyDataSetChange ().

La solution consiste à définir un rappel sur l'observateur de TabLayout et à le faire défiler lorsque les enfants sont réellement ajoutés à TabLayout. Voici mon exemple:

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

Voici mon code pour le PagerAdapter si vous en avez aussi besoin 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
Tyler

Si votre TabLayout est utilisé avec une ViewPager, ce qui est commun, ajoutez simplement ce qui suit dans la méthode onCreate() de votre activité:

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

Le fait que certains de vos onglets ne soient pas affichés indique que l'attribut tabMode est défini sur app:tabMode="scrollable".

0
barnabas

L'extrait de code ci-dessous fonctionne pour moi

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

J'ai plongé dans Tab.select (), et j'ai trouvé Android qui utilise Tablayout.setScrollPosition () pour faire ce défilement. Et dans onCreate (), les widgets n'ayant pas été mesurés, vous devez différer l'appel jusqu'à la fin de la présentation.

0
Kun Zhang