禁用TabLayout中的选项卡

10

我在我的应用中使用了最新的设计支持库中的 TabLayout。这些选项卡附加到一个 viewpager,该 viewpager 为每个选项卡加载片段。我想禁用所有选项卡,直到 viewpager 加载用户选择的选项卡的片段。我无法禁用 tablayout 或使其不可点击。我曾尝试使用 setEnabled(false)setClickable(false),但它们无效。我可以使用 setVisiblity(View.GONE) 使其不可见,但我希望选项卡始终可见。

    tabLayout = (TabLayout) findViewById(R.id.tabLayout);
    tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
    tabLayout.setTabMode(TabLayout.MODE_FIXED);
    tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.near_me_hover).setTag(1));
    tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.all_hostels).setTag(2));
    tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.top_five).setTag(3));
    tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.advanced_search).setTag(4));
    tabLayout.setEnabled(false);
    tabLayout.setClickable(false);

XML

android.support.design.widget.TabLayout
android:id="@+id/tabLayout" android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.15"
android:scrollbars="horizontal"
android:splitMotionEvents="false" >


(Note: This is already in HTML format, no need for further editing)
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            switch (tab.getPosition()) {
                case 0:
                    viewPager.setCurrentItem(tab.getPosition());
                    tab.setIcon(R.drawable.near_me_hover);
                    break;
                case 1:
                    viewPager.setCurrentItem(tab.getPosition());
                    tab.setIcon(R.drawable.all_hostels_hover);
                    break;
                case 2:
                    viewPager.setCurrentItem(tab.getPosition());
                    tab.setIcon(R.drawable.top_five_hover);
                    break;
                case 3:
                    viewPager.setCurrentItem(tab.getPosition());
                    tab.setIcon(R.drawable.advanced_search_hover);
                    break;
            }
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            switch (tab.getPosition()) {
                case 0:
                    tab.setIcon(R.drawable.near_me);
                    break;
                case 1:
                    tab.setIcon(R.drawable.all_hostels);
                    break;
                case 2:
                    tab.setIcon(R.drawable.top_five);
                    break;
                case 3:
                    tab.setIcon(R.drawable.advanced_search);

                    break;
            }

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
        }
    });
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            tabLayout.getTabAt(position).select();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
8个回答

3
您可以在 Kotlin 中创建一个实用函数,例如 myFun:
fun disableTabAt(tablayout: TabLayout?, index: Int) {
    (tablayout?.getChildAt(0) as? ViewGroup)?.getChildAt(index)?.isEnabled = false
}

当你想对一个视图进行操作时,你可以调试或者点击父视图来了解它是如何创建的。通过这种方式,你可以做任何你想做的事情。对于这种情况,你可以去查看Tablayout类来了解。


你应该考虑降低禁用选项卡的不透明度,这样它就不会看起来仍然可选; 见我的回答 - lasec0203

2

另一个技巧:

你可以在标签布局上放置另一个透明的空白视图,直到满足你的需求为止。当你需要启用/显示选项卡时,只需隐藏空白视图即可。


2
要启用特定位置的选项卡,请按以下步骤操作:

位置中指定选项卡:


LinearLayout tabStrip = ((LinearLayout)tabLayout.getChildAt(0));     
tabStrip.getChildAt(position).setOnTouchListener((v,event)->false);

禁用在位置的选项卡:

要禁用选项卡,请使用以下代码:

 tabStrip.getChildAt(position).setOnTouchListener((v,event)->true);

为什么?你能展示一下代码吗?你的需求是什么? - Minion
我的意思是它只禁用了触摸事件,用户仍然可以通过滚动视图页面进行操作。因此,在用户pager可滚动的情况下,这并不是完美的答案。 - Deepak Rajput
你看错了问题,应该查看这个链接 https://dev59.com/fF0b5IYBdhLWcg3wO_E_ - Minion

1

在标签点击监听器中实现了三种方法,其中之一是onTabSelected(),需要放置一个布尔条件来检查您的片段是否已初始化。然后,如果满足该条件,允许进行事务。还要在片段代码之后初始化选项卡。


@war_hero,如何防止TabLayout将触摸转发到ViewPager? - alsaleem
这是如何禁用它的方法。 val tabStrip = reporting_tabs.getChildAt(0) as LinearLayout for (i in 0 until tabStrip.childCount) { tabStrip.getChildAt(i).setOnTouchListener { v, event -> true } } - Minon Weerasinghe

1
这里有两个帮助函数(kotlin),可以通过传递选项卡名称来禁用和启用TabItem。
使用com.google.android.material:material:1.3.0-alpha02进行测试。
fun disableTabItemAt(tabLayout: TabLayout?, tabText: String) {
    (tabLayout?.getChildAt(0) as? ViewGroup)?.children?.iterator()?.forEach {
            if((it as TabLayout.TabView).tab?.text == tabText) {
                it.isEnabled = false
                it.alpha = 0.5f
            }
    }
}

fun enableTabItemAt(tabLayout: TabLayout?, tabText: String) {
    (tabLayout?.getChildAt(0) as? ViewGroup)?.children?.iterator()?.forEach {
        if((it as TabLayout.TabView).tab?.text == tabText) {
            it.isEnabled = true
            it.alpha = 1f
        }
    }
}

如果您的选项卡名称是固定的,那么您可以这样做:
disableTabItemAt(tabLayout, "Tab1")

// later enable it

enableTabItemAt(tabLayout, "Tab1")

0

我发现最好的解决方案是创建一个TabLayout的子类,当使用setEnabled(false)时禁用触摸交互。(请注意下面是Kotlin代码)

class NonTouchableTabLayout(context: Context,attributeSet: AttributeSet) : TabLayout(context, attributeSet) {

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return !isEnabled
    }
}

这样做还可以获得设置禁用的UI更改,并避免依赖TabLayout的内部工作方式(可能会发生变化),就像其他答案建议的那样。


0
如果您想禁用选项卡,只需使用自定义视图即可。
首先,创建您的自定义布局(以textView为例)。

v_tabview.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/tabItemView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:gravity="center"
  android:maxLines="1"
  android:textColor="@drawable/selector_tab" />

创建选择器,用于更改状态启用/禁用(更改颜色)。

selector_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="#9e9e9e" android:state_enabled="false" /> //gray
  <item android:color="#64b246" android:state_enabled="true" /> //green
</selector>

然后将其填充,设置名称并添加到tabLayout中

arrayStringNames.forEach { name ->
    val textView: TextView = inflater.inflate(R.layout.v_tabview, tabLayout, false) as TextView
    textView.text = name
    val tab = tabLayout.newTab()
    tab.customView = textView
    tabLayout.addTab(tab)
}

最后来点魔术吧!在这段示例代码中,我禁用了所有选项卡。如果您需要禁用第二个和第三个选项卡,请在循环中检查“index”,如果需要,则进行禁用。

 for (index in 0 until tabLayout.tabCount) {
   ((tabLayout.getTabAt(index)?.customView) as? TextView)?.let { textView ->
     textView.isEnabled = enable //boolean
     (textView.parent as View).enable(enable)
  }
}

-4
如果您想禁用TabLayout上的一个选项卡按钮,请尝试以下代码:
tabHost.getTabWidget().getChildTabViewAt(your_index).setEnabled(false);

2
Tabhost不是我之前用的Tablayout吗? - Abhijith Surendran
你可以尝试一下,如果有任何问题,请告诉我,我会检查一下。 - Rajan Bhavsar
我认为设计支持库中的TabHost和TabLayout是完全不同的。因此,我不能使用这种方法。 - Abhijith Surendran
让我再检查一遍。 - Rajan Bhavsar

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