Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm using the new class provided by the design library : TabLayout. And I want in specific cases that the one I'm using can't change tab anymore.

I manage to disable swipe on its viewpager but I can't figure out how to disable the change of page by clicking on tabs.

Thank's in advance.

You need to disable swipe on his ViewPager. I send you to this post : stackoverflow.com/questions/9650265/… MHogge Jan 4, 2016 at 13:28 Look at the comment above. If you don't understand the solution in the link I could try to explain it with other words. MHogge Apr 8, 2016 at 9:12 int tabPositionToDisable=1; LinearLayout tabStrip = ((LinearLayout)tablayout.getChildAt(0)); tabStrip.getChildAt(tabPositionToDisable).setClickable(false); tabStrip.getChildAt(tabPositionToDisable).setEnabled(false); pravingaikwad07 Nov 15, 2017 at 14:03

I had the same problem and I solved it disabling touch event on tabs with the following code:

  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;
                @harsh_v  this could fail in the future as Google deprecates more uses of reflection like this with each major release of Android.  Other than that it has proven safe for me in high use production applications for many years.
– pat8719
                Aug 9, 2021 at 12:59

I found a similar answer that is a little more simple and also allows you to re-enable the tabs later if you wanted to without having to deal with overriding the onTouch event.

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);

And if you want to re-enable the tabs just set tabStrip.setEnabled and setClickable for the child elements to true

LinearLayout tabStrip = ((LinearLayout)tabLayout.getChildAt(0));
tabStrip.setEnabled(true);
for(int i = 0; i < tabStrip.getChildCount(); i++) {
    tabStrip.getChildAt(i).setClickable(true);
                @user1269737 could you be more specific I'd like to fix this, what do you mean by indicator
– pat8719
                Apr 16, 2019 at 14:09
                @user1269737 thanks for pointing this out I will update my answer as I use this often enough
– pat8719
                Apr 16, 2019 at 14:33
                This answer just disable touch but by scrolling user can go to disable tab so it's not good.
– Deepak Rajput
                May 22, 2020 at 5:32

Very similar to the answer by pat8719 but just disabling the tabs is sufficient to prevent them from being selected.

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

TabLayoutUtils class

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;
bool condition = ...
foreach (var view in _tabLayout.Touchables)
    view.Clickable = condition;

This is 100% safe, as getTouchables() call is supported since API 1. No need to manually traverse layout or something. I consider it to be much simpler than that of the accepted answer, but only when all the tabs have to be marked not clickable.

P.S.: example is on C#, as I am working with Xamarin, but it is fairly easy to translate it back to Java. Enjoy! =)

Kotlin example:

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

Java example:

for (View v: tabLayout.getTouchables())
    v.setClickable(false);
                This is what I did. I also lowered the alpha on the view to have a visual indicator of the disabled/enabled state of the tab.
– natronite
                Mar 1, 2018 at 10:44
                It's worth noting that this is good for disabling, but fails to re-enable. That's because once you set a view as not-clickable, it will no longer get returned by getTouchables(). I supposed you could store the views after your first call or something, but that gets dangerous if you ever expect the hierarchy to change.
– Greyson Parrelli
                Sep 27, 2018 at 16:32
                Worked Perfectly for disabling the clickable effect, which was just what I needed.... But doesn't work if you wanna toggle it back on
– Mr Wil
                Jul 26, 2021 at 16:48
                If you are going to use ViewPager2 this solution will work in both ways. Disable and enable. stackoverflow.com/a/59864829/2469427
– Sinan Dizdarević
                Jun 2, 2022 at 22:51

A good trick you can use :

create a frame layout that cover the view(s) you want to protect from a click like the following :

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

This code will create and empty/transparent view on top of your view. The android:clickable="true" will intercept the click and prevent the click to go through the view !

This hack can probably be optimized but its few lines of code to protect multiple view at the same time !

This may be a "hack", but IMO it's a much better approach than the other answers, relying on the specifics of TabLayout's internal implementation. I needed to create an "intro" overlay over the entire app and disable everything under it while it's running, so this is a simple yet effective magic bullet. – oli.G Jul 27, 2016 at 16:28

If you are using a custom view for the Tab, you can use View#getParent() to get a reference to the Tab's View if you don't want to look through the ViewGroups.

Note: Using the custom view itself instead of the parent may not work because it can have margin, allowing the user to click in the empty space and change the tab still.

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

The OnTouchListener way and the setEnabled() way do different things, but have the same effect. I prefer the one-liner.

Again, this only works if you use a custom view, otherwise the getParent() call will cause a NullPointerException.

It's also possible to avoid child clicks by extending TabLayout class and intercepting all the touch events.

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

If you want to enable clicks again just return false on onInterceptTouchEvent method.

This is the cleanest solution imo. Other answers that rely on the internal structure of TabLayout concern me as being potentially quite fragile. I changed it a bit and implemented override fun onInterceptTouchEvent(event: MotionEvent): Boolean { return !isEnabled } So then when I set tabLayout.isEnabled = false it stops click events – Matt Smith Nov 2, 2020 at 21:51

Based on Michele's Accepted Answer, to disable click for a single tab in Kotlin:

Inside the tabs-containing activity:

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

In my use case, if the user is in a tab and presses one of the buttons, a calculation is launched and I don't want the user to be able to switch tabs until after the calculation is completed. So I used the answer by Vladislav Rishe but modified a little as follows...

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);

So when the user taps the button to make a calculation, just before the calculation logic is called, I call disableTabs(), then once the calculation is completed and it has been displayed, I call enableTabs()...

Based on this excellent solution , if someone needs it in 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

Or a more elegant solution with lambdas

mTabLayout.setOnTouchListener {v: View, m: MotionEvent ->
                There is a mistake in your kotlin code. It should be i in 0 until tabStrip.childCount. Using .. you expect an inclusive range which is not what you want here. It will crash.
– Catalin Morosan
                Aug 20, 2019 at 15:14

Disable all tabs

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

Enable all tabs

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

Where, binding.tlCommentTabs is an instance of TabLayout. I am using view binding. There is no need to add an extra wrapper view in the hierarchy.

Comprehensive solution for both ViewPager to prevent swiping between tabs, and TabLayout to prevent clicking the tabs when they are disabled.

First created the CustomViewPager and CustomTabLayout classes (inheriting the fuctionality of ViewPager and TabLayout base classes)

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

create the UI:

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

in the onCreate create the relation between the two controls:

@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 function to enable/disable the tab:

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

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.