Disable Tabs in TabLayout [duplicate]
Asked Answered
R

8

10

I have used TabLayout from the latest design support library in my app. The tabs are attached to a viewpager which loads the fragments for each tab. I want to disable all the tabs until the viewpager loads the fragment for user selected tab. I am not able to disable the tablayout or make it non-clickable. I had used setEnabled(false) and setClickable(false) but it is not working. I am able to make it invisible by using setVisiblity(View.GONE) but I want the tabs to be visible at all times.

    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" >

        @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) {

        }
    });
Relator answered 9/10, 2015 at 4:5 Comment(0)
F
1

there are 3 methods implemented by the tab click listener, one of them is onTabSelected() put a boolean condition to check if your fragment is initialised. Then if that condition is satisfied then allow transaction to take place. Also initialize the tabs after your fragment code

Falito answered 9/10, 2015 at 4:10 Comment(2)
@war_hero, how to prevent tablayout from forwarding the touch to viewpager?Berri
This is how you would disable it. val tabStrip = reporting_tabs.getChildAt(0) as LinearLayout for (i in 0 until tabStrip.childCount) { tabStrip.getChildAt(i).setOnTouchListener { v, event -> true } }Compulsion
Z
3

You can create a util function, my fun in Kotlin:

fun disableTabAt(tablayout: TabLayout?, index: Int) {
    (tablayout?.getChildAt(0) as? ViewGroup)?.getChildAt(index)?.isEnabled = false
}

When you want do something with a view, you can debug or click in parent view to know how it's created. By this way you can do anything that you want. For this case, you can go to Tablayout class to understand.

Zagreus answered 19/12, 2018 at 13:43 Comment(1)
you should consider lowering the opacity of the disabled tab also, so it doesn't look like can still be selected; see my answerParagon
A
2

Another trick:

You can put another blank transparent view upon tablayout until your requirement fulfill. When you need to enable/show the tabs then just hide the blank view.

Autocrat answered 7/6, 2016 at 7:55 Comment(0)
C
2

To enable specific tab at position :

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

To disable the tab at position :

 tabStrip.getChildAt(position).setOnTouchListener((v,event)->true);
Cumulative answered 27/6, 2019 at 13:14 Comment(3)
Why? can you show the code? what is your requirement?Cumulative
I means it only disable the touch event user can still go by scrolling view pager. so it's not perfect annwer in case userpager is scrollable.Zinfandel
You are looking at the wrong question, check this one #29442716Cumulative
F
1

there are 3 methods implemented by the tab click listener, one of them is onTabSelected() put a boolean condition to check if your fragment is initialised. Then if that condition is satisfied then allow transaction to take place. Also initialize the tabs after your fragment code

Falito answered 9/10, 2015 at 4:10 Comment(2)
@war_hero, how to prevent tablayout from forwarding the touch to viewpager?Berri
This is how you would disable it. val tabStrip = reporting_tabs.getChildAt(0) as LinearLayout for (i in 0 until tabStrip.childCount) { tabStrip.getChildAt(i).setOnTouchListener { v, event -> true } }Compulsion
P
1

Here's 2 helper functions (kotlin) for disabling and enabling a TabItem by passing its name.

Tested using 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
        }
    }
}

So if your tab names are fixed, then you could do

disableTabItemAt(tabLayout, "Tab1")

// later enable it

enableTabItemAt(tabLayout, "Tab1")
Paragon answered 27/10, 2020 at 2:1 Comment(0)
M
0

If you want to disable tab, you just need use a customView

First at all, create your custom layout (textView as an example)

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" />

create selector, for changing state enable/disable (changing color)

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>

then inflate it, set names and add to the 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)
}

and at the end, a magic trick! In that sample code I disabling all tabs. If you need disable second and third tab, check "index" in a cycle and disable if you need

 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)
  }
}
Mose answered 27/4, 2018 at 7:48 Comment(0)
A
0

I've found the best solution is to create a child of TabLayout that disables the touch interaction when using setEnabled(false). (note the below is Kotlin)

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

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

This way you also get the UI changes of setting it disabled and you avoid relying on the inner workings of TabLayout (which may change) like some of the other answers suggest.

Acorn answered 2/11, 2020 at 22:54 Comment(0)
H
-4

If you mean to disable one tab button on TabLayout, then try this code:

tabHost.getTabWidget().getChildTabViewAt(your_index).setEnabled(false);
Hanser answered 9/10, 2015 at 4:11 Comment(4)
Isn't tabhost different from the tablayout that i had used?Relator
You can try if having any Issue then let me know i will check it out.Hanser
I think tabhost and tablayout from the design support library are entirely different. So i cant use this method.Relator
LEt me check that Again.Hanser

© 2022 - 2024 — McMap. All rights reserved.