选项卡布局(TabLayout)选项卡选择

309

我应该如何在TabLayout中以编程方式选择选项卡?

 TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
 tabLayout.setupWithViewPager(viewPager);
29个回答

511

如果您知道要选择哪个选项卡的索引,可以这样做:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
tab.select();

即使您在不使用ViewPager的情况下仅使用TabLayout这种技术也可以工作(尽管这是不典型的且可能是不好的实践,但我看过它被使用)。


12
这个解决方案只适用于选项卡已经添加到操作栏的情况,但并非总是如此。从TabLayout.Tab.select()的文档中可以看到:"选择此选项卡。仅当选项卡已添加到操作栏时才有效。" - Daniel Kvist
8
@DanielKvist,实际上文档本身是错误的。源代码说明问题。这个回答应该被接受。 - Jason Sparc
@JasonSparc 嗯,我记得上次尝试这个解决方案时它对我无效,但我会再检查一下它对我是如何工作的。你试过吗?在某些情况下可能有效,而在其他情况下可能无效。可能取决于API级别或类似的东西。 - Daniel Kvist
感谢您澄清了半成品答案的问题!因为这在独立的TabLayout上可能行不通,可能正如您所说的那样;它是用于与Actionbar中的选项卡一起使用的! - sud007
6
为什么在没有ViewPager的情况下使用TabLayout应被视为不良实践? - tomalf2
显示剩余3条评论

101

这是我解决问题的方法:

void selectPage(int pageIndex){
    tabLayout.setScrollPosition(pageIndex,0f,true);
    viewPager.setCurrentItem(pageIndex);
}

3
之前选择的答案对我没有用,但这个答案有效。 - Rafal Zawadzki
1
很棒的解决方案!当我需要将ViewPager和TabView都移回第一页时,它对我非常有效。 - sashk0
有风险的侧面。它会防止创建其他选项卡。 - Arda Kazancı

89

使用这个:

tabs.getTabAt(index).select();
请记住,如果currentTabIndex和index相同,则会将您的流程发送到onTabReselected而不是onTabSelected。

谢谢,这对我的实现来说是一个安全的解决方案。 - Islam Mansour
Objects.requireNonNull(tabs.getTabAt(position)).select(); 的使用是安全的。 - Williaan Lopes
2
请注意,如果 currentTabIndex 和 index 相同,则会将您的流程发送到 onTabReselected 而不是 onTabSelected。 - Abhishek Kumar
2
@WilliaanLopes,这并不能保护你免受NPI的侵害,只会更早地抛出它。 - Krzysztof Kubicki

42

使用这个:

<android.support.design.widget.TabLayout
    android:id="@+id/patienthomescreen_tabs"
    android:layout_width="match_parent"
    android:layout_height="72sp"
    app:tabGravity="fill"
    app:tabMode="fixed"
    app:tabIndicatorColor="@android:color/white"
    app:tabSelectedTextColor="@color/green"/>

在OnClickListener之后:

TabLayout tabLayout = (TabLayout) findViewById(R.id.patienthomescreen_tabs);
TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
tab.select();

请记住,如果 currentTabIndex 和 index 相同,这将使您的流程发送到 onTabReselected 而不是 onTabSelected。


如果tabMode是可滚动的呢? - GvSharma
我认为一样,请你先尝试一下。 - Pravin Suthar
不需要将其存储在变量中 tabLayoutSensor.getTabAt(0)?.select() - joninx

27

这可能不是最终解决方案需要您使用TabLayoutViewPager一起使用,但这就是我解决它的方式:

void selectPage(int pageIndex)
{
    viewPager.setCurrentItem(pageIndex);
    tabLayout.setupWithViewPager(viewPager);
}

我测试了使用这段代码的性能影响有多大,首先在运行该方法时观察Android Studio中的CPU和内存监视器,然后将其与我自己在页面之间导航时(使用滑动手势)对CPU和内存产生的负载进行比较,差异并不显著,所以至少它不是一个糟糕的解决方案...

希望这能帮助到某些人!


1
当我使用dap的解决方案(tabLayout.setScrollPosition(pageIndex,0f,true);)时,当我点击右侧的标签时,它没有更新ViewPager的页面(我不知道为什么)。只有先点击左侧选项卡,然后再点击右侧选项卡才能最终更新页面以显示正确的选项卡页面,这非常不稳定。但是这个解决方案没有任何故障。 - Rock Lee

15

只需设置viewPager.setCurrentItem(index),相关的TabLayout将选择相应的选项卡。


这对我没有用。我不得不使用.post方法。 - arenaq

15

不行,selectTab是一个包私有方法。 - X.Y.
@xyuber.com我添加了重要信息。它需要版本1.1.0。该方法现在是公共的 - Gabriele Mariotti
索引在哪里? - Krishna Ch

13

如果您无法使用tab.select(),并且不想使用ViewPager,仍然可以以编程方式选择选项卡。如果您正在使用通过TabLayout.Tab setCustomView(android.view.View view)自定义视图,那么这将更简单。以下是两种方法的实现。

// if you've set a custom view
void updateTabSelection(int position) {
    // get the position of the currently selected tab and set selected to false
    mTabLayout.getTabAt(mTabLayout.getSelectedTabPosition()).getCustomView().setSelected(false);
    // set selected to true on the desired tab
    mTabLayout.getTabAt(position).getCustomView().setSelected(true);
    // move the selection indicator
    mTabLayout.setScrollPosition(position, 0, true);

    // ... your logic to swap out your fragments
}

如果您没有使用自定义视图,则可以按照以下方式进行操作

// if you are not using a custom view
void updateTabSelection(int position) {
    // get a reference to the tabs container view
    LinearLayout ll = (LinearLayout) mTabLayout.getChildAt(0);
    // get the child view at the position of the currently selected tab and set selected to false
    ll.getChildAt(mTabLayout.getSelectedTabPosition()).setSelected(false);
    // get the child view at the new selected position and set selected to true
    ll.getChildAt(position).setSelected(true);
    // move the selection indicator
    mTabLayout.setScrollPosition(position, 0, true);

    // ... your logic to swap out your fragments
}

使用StateListDrawable来切换选择和未选择的可绘制对象,或使用类似的东西来实现您想要的颜色和/或可绘制对象。


12

有点晚了,但可能是一个有用的解决方案。 我直接在我的Fragment中使用TabLayout,并尝试在Fragment的生命周期很早的阶段选择一个标签。 对我有用的是等待TabLayout完成其子视图的绘制,使用android.view.View#post方法。即:

int myPosition = 0;
myFilterTabLayout.post(() -> { filterTabLayout.getTabAt(myPosition).select(); });

2
正确的答案对我有用,但稍微延迟一下会让它更加完美。new Handler().postDelayed(() -> { tabLayout.post(() -> { tabLayout.getTabAt(myPosition).select(); }); }, 200); - Hisham
@Hisham,我不喜欢在编程中使用延迟钩子..不幸的是这是唯一安全的方法,特别是在Pager2中.. - Maher Abuthraa
我不建议使用Handler.postDelayed这种解决方案,因为如果用户非常快地退出屏幕,它可能会导致NPE:在延迟200后,你的tabLayout可能已经不存在了... - ahmed_khan_89

9
您可以尝试使用以下方法解决它:
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);

TabLayout.Tab tab = tabLayout.getTabAt(pos);
if (tab != null) {
    tab.select();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接