Android TabWidget detect click on current tab
Asked Answered
D

9

39

I am trying to find way to be able to fire an onclick event on a tab when this tab is the current tab.

I did try this way (among several other) with no success thou.

public void onTabChanged(String tabId) {
    Log.d(this.getClass().getName(), ">>>>>>>>>>>>>>>>>>>>>>>> tabId: " + tabId);

    int tabs = getTabWidget().getChildCount();
    Log.d(this.getClass().getName(), "tabs: " + tabs);
    for(int i=0; i<tabs; i++){
        View tab = getTabWidget().getChildAt(i);
        if(i==tabHost.getCurrentTab()){
            Log.d(this.getClass().getName(), "tab: " + i);
            tab.setOnClickListener(this);
        }else{
            tab.setOnClickListener(null);
            tab.getOnFocusChangeListener();
        }
    }   
}

the point is that I set the onClickListener to null so, the next time I click on a tab nothing happens, but I would like to have the normal tab behavior.

Any idea there outside?

Dung answered 2/12, 2010 at 16:48 Comment(4)
"I am trying to find way to be able to fire an onclick event on a tab when this tab is the current tab." -- that is not a very discoverable UI pattern. Users do not expect a tap on the current tab to do anything. I encourage you to reconsider your approach.Object
I agree with you, my customer dose not :/Dung
i have a similar situation where each tab has instructions for the user and i want them to be able to click the tab again for the directions to be shown again. i guess it is an unusual pattern but it is the only one i have thought of to make the directions easily reviewableFrizzy
After trying most of the solutions in this thread, I finally solve this problem in just 5 minutes using this answer.Photo
D
20

I think I have found a solution, here follows a sample code:

    intent = new Intent(this, HomeGroup.class);
    View tab1 = _inflater.inflate(R.layout.custom_tab_1,null);
    homeTab.setTag("Tab1");
    spec = tabHost.newTabSpec("Tab1").setIndicator(tab1).setContent(intent);
    tabHost.addTab(spec);

    View tab2 = _inflater.inflate(R.layout.custom_tab_2,null);
    homeTab.setTag("Tab2");
    spec = tabHost.newTabSpec("Tab2").setIndicator(tab2).setContent(intent);
    tabHost.addTab(spec);

    View tab3 = _inflater.inflate(R.layout.custom_tab_3,null);
    homeTab.setTag("Tab3");
    spec = tabHost.newTabSpec("Tab3").setIndicator(tab3).setContent(intent);
    tabHost.addTab(spec);

    tabHost.setOnTabChangedListener(this);

    //click on seleccted tab
    int numberOfTabs = tabHost.getTabWidget().getChildCount();
    for(int t=0; t<numberOfTabs; t++){
        tabHost.getTabWidget().getChildAt(t).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction()==MotionEvent.ACTION_UP){

                    String currentSelectedTag = MainTab.this.getTabHost().getCurrentTabTag();
                    String currentTag = (String)v.getTag();
                    Log.d(this.getClass().getSimpleName(), "currentSelectedTag: " + currentSelectedTag + " currentTag: " + currentTag);
                    if(currentSelectedTag.equalsIgnoreCase(currentTag)){
                        MainTab.this.getTabHost().setCurrentTabByTag(currentTag);
                        String newSelectedTabTag = MainTab.this.getTabHost().getCurrentTabTag();
                        if(newSelectedTabTag.toLowerCase().indexOf("tab1")!=-1){
                            //do smthg
                        }else if(newSelectedTabTag.toLowerCase().indexOf("tab1")!=-1){
                            //do smthg
                        }else if(newSelectedTabTag.toLowerCase().indexOf("tab3")!=-1){
                            //do smthg
                        }
                        return true;
                    }
                }
                return false;
            }
        });
    }       

Probably it is possible to improve it, but this does the work for me!

Dung answered 4/2, 2011 at 11:46 Comment(4)
v.getTag() return null for me.Mucro
@ 0m4r ........ can you look into this question ..... stackoverflow.com/q/19269322/2825729Servile
@ 0m4r - Can you please tell me what refers homeTab?Obverse
@Obverse homeTab is the view to display when i press a tab button (probably in the snippet above, the fact that I have more then one homeTab is a cut&past error....)Dung
M
51

After gothrough many solutions for tab listener, I have found very simple solution...

getTabHost().setOnTabChangedListener(new OnTabChangeListener() {

@Override
public void onTabChanged(String tabId) {

int i = getTabHost().getCurrentTab();
 Log.i("@@@@@@@@ ANN CLICK TAB NUMBER", "------" + i);

    if (i == 0) {
            Log.i("@@@@@@@@@@ Inside onClick tab 0", "onClick tab");

    }
    else if (i ==1) {
            Log.i("@@@@@@@@@@ Inside onClick tab 1", "onClick tab");
    }

  }
});
Meniscus answered 13/10, 2011 at 6:39 Comment(5)
This doesn't solve the OPs problem: this only gets called when the tab has changed and not when clicking the same tab.Brethren
Thanks man, you helped me to finish one long and crazy projectScary
@Meniscus great answer :-), I have been stuck for last 3 days and this answer solved my exact problem ;)Azarcon
@Brethren : You should disable current tab to avoid click again. It would be more familiar with users.Capparidaceous
@TranDucHuy - a disabled tab may not be what users want or expect - it all depends on the use case, and as I mentioned, it's not what was asked.Brethren
P
24

After a lot of thinking about this, the solution ended up being easier than I thought. What I did was just create a new child class that extends TabHost and override the setCurrentTab method like so:

package com.mycompany.Views;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TabHost;
import android.widget.Toast;

public class ReclickableTabHost extends TabHost {

    public ReclickableTabHost(Context context) {
        super(context);
    }

    public ReclickableTabHost(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setCurrentTab(int index) {
        if (index == getCurrentTab()) {
            // FIRE OFF NEW LISTENER
        } else {
            super.setCurrentTab(index);
        }
    }
}

To use your new class instead of the typical TabHost just edit your layout xml file with:

<FrameLayout
    android:layout_height="match_parent"
    android:layout_width="0dip"
    android:layout_weight=".8">

    <com.myCompany.Views.ReclickableTabHost
        android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/tab_unselected_holo"/>
            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
            </FrameLayout>

        </LinearLayout>

    </com.myCompany.Views.ReclickableTabHost>

Hope this helps...

Psychology answered 15/2, 2012 at 21:31 Comment(3)
Seems like the most reliable solution. Thanks Steve.Brethren
Great answer. I added public interface OnReClickListener { public void onReClick(int index); } an and ivar private OnReClickListener onReClickListener; (plus getters and setters) as well as this code to fire off the listener: if (null != onReClickListener) { onReClickListener.onReClick(index);} Hope that helps.Codger
It is also important to add check isShown() before notifying listener. Because android calls setCurrentTab if user locks/unlocks device.Carlyncarlynn
D
20

I think I have found a solution, here follows a sample code:

    intent = new Intent(this, HomeGroup.class);
    View tab1 = _inflater.inflate(R.layout.custom_tab_1,null);
    homeTab.setTag("Tab1");
    spec = tabHost.newTabSpec("Tab1").setIndicator(tab1).setContent(intent);
    tabHost.addTab(spec);

    View tab2 = _inflater.inflate(R.layout.custom_tab_2,null);
    homeTab.setTag("Tab2");
    spec = tabHost.newTabSpec("Tab2").setIndicator(tab2).setContent(intent);
    tabHost.addTab(spec);

    View tab3 = _inflater.inflate(R.layout.custom_tab_3,null);
    homeTab.setTag("Tab3");
    spec = tabHost.newTabSpec("Tab3").setIndicator(tab3).setContent(intent);
    tabHost.addTab(spec);

    tabHost.setOnTabChangedListener(this);

    //click on seleccted tab
    int numberOfTabs = tabHost.getTabWidget().getChildCount();
    for(int t=0; t<numberOfTabs; t++){
        tabHost.getTabWidget().getChildAt(t).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction()==MotionEvent.ACTION_UP){

                    String currentSelectedTag = MainTab.this.getTabHost().getCurrentTabTag();
                    String currentTag = (String)v.getTag();
                    Log.d(this.getClass().getSimpleName(), "currentSelectedTag: " + currentSelectedTag + " currentTag: " + currentTag);
                    if(currentSelectedTag.equalsIgnoreCase(currentTag)){
                        MainTab.this.getTabHost().setCurrentTabByTag(currentTag);
                        String newSelectedTabTag = MainTab.this.getTabHost().getCurrentTabTag();
                        if(newSelectedTabTag.toLowerCase().indexOf("tab1")!=-1){
                            //do smthg
                        }else if(newSelectedTabTag.toLowerCase().indexOf("tab1")!=-1){
                            //do smthg
                        }else if(newSelectedTabTag.toLowerCase().indexOf("tab3")!=-1){
                            //do smthg
                        }
                        return true;
                    }
                }
                return false;
            }
        });
    }       

Probably it is possible to improve it, but this does the work for me!

Dung answered 4/2, 2011 at 11:46 Comment(4)
v.getTag() return null for me.Mucro
@ 0m4r ........ can you look into this question ..... stackoverflow.com/q/19269322/2825729Servile
@ 0m4r - Can you please tell me what refers homeTab?Obverse
@Obverse homeTab is the view to display when i press a tab button (probably in the snippet above, the fact that I have more then one homeTab is a cut&past error....)Dung
P
15

Ugly fix:IN the onClickListener put : tabHost.SetCurrentTab(OtherTab); tabHost.SetCurrentTab(CurrentTab); Where for index of Other Tab I use my simplest view under the tabs.

P.S. Customers always want their apps to be different :)

This is the code that I use (I have only 2 tabs Tab1 and Tab2):

 getTabWidget().getChildAt(1).setOnClickListener(new OnClickListener() { 
            @Override 
            public void onClick(View v) { 

                Log.d(TAG,"1"+getTabHost().getCurrentTabTag());

                if (getTabHost().getCurrentTabTag().equals("Tab2")) { 
                    Log.d(TAG,"2");

                    tabHost.setCurrentTab(0);                                    
                    tabHost.setCurrentTab(1);

                } else {
                    tabHost.setCurrentTab(1);
                }
            } 
        });
Porringer answered 3/12, 2010 at 20:55 Comment(4)
what do you mean with " Where for index of Other Tab I use my simplest view under the tabs."?Dung
I have been trying your solution but I still have the problem that overrriding the default onClick event on the tab I override the default behavior... and setting it to null remove the onClick event at all.... so, thanks for your help but I think I can't use your solution unless I rewrite the whole onClick event for the tab :/Dung
useful with two tabs, with more than two I would not know how to manage it :) But thanks anyhow!Dung
override the onTouchListener instead and return false inside onTouch, Using onClick will cause the tabs to stop changingLipkin
A
5

The problem here is that setOnTabChangedListener does not fire when clicking on the selected tab, and if you set an OnClickListener on the tab, you lose the normal tab behavior.

So an easy solution is to put OnClickListener on the tab, and inside it, set programatically that this is the current tab.

With TabHost:

getTabWidget().getChildAt(0).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // custom code
        tabHost.setCurrentTab(0);                                    
    }
});

With TabLayout

tabLayout.getTabAt(0)setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                    // custom code
                    TabLayout.Tab tab  = tabLayout.getTabAt(0);
                    tab.select();
                }
            }
        });
Aurelie answered 24/2, 2016 at 12:1 Comment(0)
S
4

If you want to try android.support.design.widget.TabLayout, you can achieve it like this:

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
   @Override public void onTabSelected(Tab tab) {

   }

   @Override public void onTabUnselected(Tab tab) {

   }

   @Override public void onTabReselected(Tab tab) {

   }
});
Stob answered 9/12, 2016 at 17:33 Comment(1)
Hey @AmiAram, thanks for your edit. Unfortunately, it didn't go through. But it is good suggestion and I changed my answer with that!Stob
P
1
mTabHost.setOnTabChangedListener(new OnTabChangeListener() {

        @Override
        public void onTabChanged(String tabId) {

            int i = mTabHost.getCurrentTab();
            mTabHost.getTabWidget().getChildAt(i)
                    .setBackgroundColor(Color.parseColor("#014a68"));

            //int m = mTabHost.getChildCount();
            for (int j = 0; j <=3; j++) {
                if (j != i)
                    mTabHost.getTabWidget()
                            .getChildAt(j)
                            .setBackgroundColor(Color.parseColor("#000000"));
            }


        }
    });
Postdate answered 1/11, 2015 at 9:22 Comment(0)
A
1

This is working for me...

TabHost host = (TabHost)findViewById(R.id.tabHost);

host.setOnTabChangedListener(new OnTabChangeListener() {
    @Override
    public void onTabChanged(String tabId) {

        int i = host.getCurrentTab();

        if (i == 0) {
             // your method 1
        }
        else if (i ==1) {
            // your method 2
        }
    }
});
Antoninaantonino answered 23/12, 2017 at 16:2 Comment(0)
A
0

If you have a custom tab layout, you might need to add this in your custom view, it solved my problem:

android:duplicateParentState="true"
Apish answered 28/4, 2017 at 12:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.