禁用TabLayout

56 人关注

我正在使用设计库提供的新类:TabLayout。我希望在特定情况下,我使用的这个类不能再改变标签。

我设法在其viewpager上禁用刷卡,但我不知道如何通过点击标签来禁用页面的变化。

提前感谢。

5 个评论
你是如何禁用刷卡的?
你需要在他的ViewPager上禁用刷卡。我把你送到这个帖子。 stackoverflow.com/questions/9650265/...
@Shargotth 你是如何禁用刷卡的?
请看上面的评论。如果你不理解链接中的解决方案,我可以试着用其他语言来解释它。
int tabPositionToDisable=1; LinearLayout tabStrip = ((LinearLayout)tablayout.getChildAt(0)); tabStrip.getChildAt(tabPositionToDisable).setClickable(false); tabStrip.getChildAt(tabPositionToDisable).setEnabled(false) 。
android
disabled-control
android-tablayout
MHogge
MHogge
发布于 2015-07-29
13 个回答
Michele
Michele
发布于 2022-02-13
已采纳
0 人赞同

我也有同样的问题,我用下面的代码解决了禁用标签上的触摸事件。

  LinearLayout tabStrip = ((LinearLayout)mTabLayout.getChildAt(0));
    for(int i = 0; i < tabStrip.getChildCount(); i++) {
        tabStrip.getChildAt(i).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
    
对我来说也是如此。谢谢!
我在 onCreateView 中调用了这些行,但没有用。
这样做效果非常好,但它安全吗?是否有任何可能失败的情况?
@harsh_v 这在未来可能会失败,因为Google在每个主要的Android版本中都会废弃更多像这样的反射用法。 除此之外,多年来,在高使用率的生产应用中,它对我来说是安全的。
pat8719
pat8719
发布于 2022-02-13
0 人赞同

我找到了一个类似的答案,它更简单一些,而且还允许你以后重新启用标签,如果你想的话,不必处理覆盖onTouch事件。

TabLayout tabLayout = (TabLayout)  mParentView.findViewById(R.id.my_tabs);
LinearLayout tabStrip = ((LinearLayout)tabLayout.getChildAt(0));
tabStrip.setEnabled(false);
for(int i = 0; i < tabStrip.getChildCount(); i++) {
    tabStrip.getChildAt(i).setClickable(false);

如果你想重新启用标签,只需将tabStrip.setEnabled和setClickable的子元素设置为true。

LinearLayout tabStrip = ((LinearLayout)tabLayout.getChildAt(0));
tabStrip.setEnabled(true);
for(int i = 0; i < tabStrip.getChildCount(); i++) {
    tabStrip.getChildAt(i).setClickable(true);
    
@user1269737 你能不能说得更具体一点,我想解决这个问题,你说的指标是什么意思?
有文本和指标(文本下面的线)。这个指标仍然是可以点击的。
@user1269737 谢谢你指出这一点,我将更新我的答案,因为我经常使用这个。
这个答案只是禁止触摸,但通过滚动用户可以进入禁止的标签,所以这不是很好。
grantnz
grantnz
发布于 2022-02-13
0 人赞同

与pat8719的答案非常相似,但只是禁用标签就足以防止它们被选中。

TabLayout tabLayout = (TabLayout)  mParentView.findViewById(R.id.my_tabs);
TabLayoutUtils.enableTabs( tabLayout, false );

TabLayoutUtils类

public class TabLayoutUtils {
    public static void enableTabs(TabLayout tabLayout, Boolean enable){
        ViewGroup viewGroup = getTabViewGroup(tabLayout);
        if (viewGroup != null)
            for (int childIndex = 0; childIndex < viewGroup.getChildCount(); childIndex++)
                View tabView = viewGroup.getChildAt(childIndex);
                if ( tabView != null)
                    tabView.setEnabled(enable);
    public static View getTabView(TabLayout tabLayout, int position){
        View tabView = null;
        ViewGroup viewGroup = getTabViewGroup(tabLayout);
        if (viewGroup != null && viewGroup.getChildCount() > position)
            tabView = viewGroup.getChildAt(position);
        return tabView;
    private static ViewGroup getTabViewGroup(TabLayout tabLayout){
        ViewGroup viewGroup = null;
        if (tabLayout != null && tabLayout.getChildCount() > 0 ) {
            View view = tabLayout.getChildAt(0);
            if (view != null && view instanceof ViewGroup)
                viewGroup = (ViewGroup) view;
        return viewGroup;
    
Vladislav Rishe
Vladislav Rishe
发布于 2022-02-13
0 人赞同

对我来说,工作方法是这样的。

bool condition = ...
foreach (var view in _tabLayout.Touchables)
    view.Clickable = condition;

这是100%安全的,因为getTouchables()从API 1开始就支持调用,不需要手动遍历布局或其他。我认为这比已接受的答案要简单得多,但只有当所有的标签都必须被标记为不可点击时。

P.S.: 例子是关于C#的,因为我是用Xamarin工作的,但把它翻译成Java是相当容易的。请欣赏!=)

Kotlin的例子。

tabLayout.touchables.forEach { it.isClickable = false }

Java的例子。

for (View v: tabLayout.getTouchables())
    v.setClickable(false);
    
natronite
这就是我所做的。我还降低了视图的阿尔法值,以便对标签的禁用/启用状态有一个视觉指示。
值得注意的是,这对禁用有好处,但不能重新启用。这是因为一旦你把一个视图设置为不可点击,它将不再被getTouchables()返回。我想你可以在第一次调用后存储视图或其他东西,但如果你希望层次结构发生变化,这就很危险了。
我想拨动它。我无法将可点击打开。
对于禁用可点击的效果来说,工作非常完美,这正是我所需要的....。但如果你想把它重新打开,就无法工作了
如果你要使用ViewPager2,这个解决方案将在两种情况下都适用。禁用和启用。 stackoverflow.com/a/59864829/2469427
Tobliug
Tobliug
发布于 2022-02-13
0 人赞同

你可以使用一个好的技巧:

创建一个框架布局,覆盖你想保护的视图,使其不受点击的影响,如下所示。

<FrameLayout
    android:clickable="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

这段代码将在你的视图上面创建一个空的/透明的视图。 android:clickable="true "将拦截点击,并防止点击通过视图 !

这个黑客可能会被优化,但它的几行代码可以同时保护多个视图!

这可能是一个 "黑客",但在我看来,这比其他答案要好得多,因为它依赖于TabLayout内部实现的具体情况。我需要在整个应用程序上创建一个 "介绍 "覆盖层,并在它运行时禁用它下面的所有东西,所以这是一个简单而有效的灵丹妙药。
Best solution ever
Jacob Muchow
Jacob Muchow
发布于 2022-02-13
0 人赞同

如果你为Tab使用自定义视图,如果你不想通过ViewGroups查看,你可以使用View#getParent()来获得对Tab的视图的引用。

注意:使用自定义视图本身而不是父视图可能不奏效,因为它可以有边际,允许用户在空白处点击并改变标签仍。

View tabView = (View) tab.getCustomView().getParent();
tabView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
tabView.setEnabled(false);

OnTouchListener方式和setEnabled()方式做了不同的事情,但有相同的效果。我更喜欢那个单行本。

再一次。这只有在你使用自定义视图时才有效,否则调用getParent()会导致NullPointerException。

Cedulio Cezar
Cedulio Cezar
发布于 2022-02-13
0 人赞同

也可以通过扩展TabLayout类和拦截所有的触摸事件来避免孩子的点击。

class NonTouchableTabLayout : TabLayout {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return true

如果你想再次启用点击,只需在interceptTouchEvent方法上返回false。

这是最干净的解决方案,我认为。其他依赖于TabLayout内部结构的答案让我担心可能会相当脆弱。 我改变了一下,实现了 override fun onInterceptTouchEvent(event: MotionEvent): Boolean { return !isEnabled } 。所以,当我设置 tabLayout.isEnabled = false 时,它就会停止点击事件
0 人赞同

根据Michele的已接受答案,要禁止点击一个 单一标签 in Kotlin :

在包含标签的活动中。

val tabs: TabLayout = findViewById(R.id.tabs)
(tabs.getChildAt(0) as LinearLayout).getChildAt(desiredTabPositionHere).isClickable = false

你可以把点击功能开和关(通过设置truefalse)。用同样的方法,也可以修改visibility, 阿尔法, 背景颜色 etc.

phantomBlurrr
phantomBlurrr
发布于 2022-02-13
0 人赞同

在我的用例中,如果用户在一个选项卡中按下其中一个按钮,就会启动一个计算,我不希望用户在计算完成之前能够切换选项卡。所以我使用了Vladislav Rishe的答案,但做了一点修改,如下所示...

In JAVA :

//'tabLayout' is the variable where you reference your tab layout...
//A container to save the tabs that were disabled
private ArrayList<View> touchablesToRestore = new ArrayList<View>();
public void enableTabs() {
    for(View v: touchablesToRestore){
        v.setClickable(true);
    //After you enable them all, clear the container
    touchablesToRestore.clear();
public void disableTabs(){
    for(View v: tabLayout.getTouchables()){
        //Add the tab that is being disabled to the container
        touchablesToRestore.add(v);
        v.setClickable(false);

因此,当用户点击按钮进行计算时,就在计算逻辑被调用之前,我调用disableTabs(),然后一旦计算完成并被显示出来,我就调用enableTabs()

Mạnh Hoàng Huynh
Mạnh Hoàng Huynh
发布于 2022-02-13
0 人赞同

在此查看我的答案 禁用TabLayout中的标签

你可以为循环标签,并使用这个函数来禁用所有标签

BMU
BMU
发布于 2022-02-13
0 人赞同

基于这个优秀的解决方案,如果有人需要它在Kotlin。

  val tabStrip = mTabLayout.getChildAt(0) as LinearLayout
    for (i in 0..tabStrip.childCount) {
        tabStrip.getChildAt(i).setOnTouchListener(object : View.OnTouchListener{
            override fun onTouch(p0: View?, p1: MotionEvent?): Boolean {
                return true

或者用lambdas的一个更优雅的解决方案

mTabLayout.setOnTouchListener {v: View, m: MotionEvent ->
    
你的kotlin代码中有一个错误。它应该是i在0直到tabStrip.childCount。使用......你期望的是一个包容性的范围,这不是你想要的。它将会崩溃。
Parth Patel
Parth Patel
发布于 2022-02-13
0 人赞同

We can disable & re-enable all tabs as below:

Kotlin

禁用所有标签

fun disableAllTabs() {
    (binding.tlCommentTabs.getChildAt(0) as? ViewGroup)?.forEach { it.isEnabled = false }
    (binding.tlCommentTabs.getChildAt(1) as? ViewGroup)?.forEach { it.isEnabled = false }

启用所有标签

fun enableAllTabs() {
    (binding.tlCommentTabs.getChildAt(0) as? ViewGroup)?.forEach { it.isEnabled = true }
    (binding.tlCommentTabs.getChildAt(1) as? ViewGroup)?.forEach { it.isEnabled = true }
binding.tlCommentTabs是TabLayout的一个实例。我正在使用视图绑定。没有必要在层次结构中添加一个额外的包装视图。

ZP007
ZP007
发布于 2022-02-13
0 人赞同

全面解决ViewPager防止在标签之间滑动的问题,以及TabLayout防止在禁用标签时点击标签的问题。

首先创建了CustomViewPager和CustomTabLayout类(继承了ViewPager和TabLayout基类的功能)。

// content of CustomViewPager.java
package mypackage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
public class CustomViewPager extends ViewPager {
    private boolean enableSwipe;
    public CustomViewPager(Context context) {
        super(context);
        init();
    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    private void init() {
        enableSwipe = true;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return enableSwipe && super.onInterceptTouchEvent(event);
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return enableSwipe && super.onTouchEvent(event);
    public void setEnableSwipe(boolean enableSwipe) {
        this.enableSwipe = enableSwipe; 
// content of CustomTabLayout.java
package mypackage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.google.android.material.tabs.TabLayout;
public class CustomTabLayout extends TabLayout {
    private boolean enableTabs;
    public CustomTabLayout(Context context) {
        super(context);
        init();
    public CustomTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    private void init() {
        enableTabs = true;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return !enableTabs;
    public void setEnableTabs(boolean enable) {
        this.enableTabs = enable;

创建用户界面。

        <mypackage.CustomTabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary" />
        <mypackage.CustomViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="100dp"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

在onCreate中创建两个控件之间的关系。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CustomViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        CustomTabLayout tabs = findViewById(R.id.tabs);
        tabs.setupWithViewPager(viewPager);

EnableControls函数来启用/禁用标签。

private void EnableControls(boolean b) {
        CustomViewPager viewPager = findViewById(R.id.view_pager);
        CustomTabLayout tabs = findViewById(R.id.tabs);