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?
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);
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();
}
});
é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();
}
});
}
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.
Pour sélectionner le dernier onglet, utilisez TabLayout.getTabAt (X) .select (); où X est le dernier index de tabulation
new Handler().postDelayed(
new Runnable() {
@Override public void run() {
mTabLayout.getTabAt(TAB_NUMBER).select();
}
}, 100);
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.
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
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);
viewpager.setItem(position)
devrait également définir la position de la tabulation
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;
}
}
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"
.
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.