16

I implemented a TabActivity which implements the OnTabChangeListener. The activity will be notified on tab changes (onTabChanged(String tabId)).

Is it also possible to get notified if the user selects the current tab again?

I would like to use this event to perform a "refresh" of the current tab content instead of providing a refresh button on the tab or in the options menu.


That's the way I finally solved the problem - solution hint was in MisterSquonk answer.

(1) Define a OnTabReselectListener which must be implemented by an activity which represents a tab content and which will be notified on reselect events.

/**
 * Interface definition for a callback to be invoked when a current selected tab
 * in a TabHost is selected again.
 */
public interface OnTabReselectListener {

    /**
     * Called when a current visible tab is selected again. Will not be invoked
     * on tab changes.
     */
    void onTabReselect();

}

(2) setOnTouchListener for each tabWidget child in onCreate() of the TabActivity (from MisterSquonk's answer)

for (int i = 0; i < tabWidget.getChildCount(); i++) {
    View v = tabWidget.getChildAt(i);
    v.setOnTouchListener(this);
}

(3) Implement OnTouchListener.onTouch() in the TabActivity. Do some logic to decide if the current tab was selected again and notifiy the tab's activity.

/**
 * @see android.view.View.OnTouchListener#onTouch(android.view.View,
 *      android.view.MotionEvent)
 */
@Override
public boolean onTouch(View v, MotionEvent event) {
    boolean consumed = false;
    // use getTabHost().getCurrentTabView to decide if the current tab is
    // touched again
    if (event.getAction() == MotionEvent.ACTION_DOWN
            && v.equals(getTabHost().getCurrentTabView())) {
        // use getTabHost().getCurrentView() to get a handle to the view
        // which is displayed in the tab - and to get this views context
        View currentView = getTabHost().getCurrentView();
        Context currentViewContext = currentView.getContext();
        if (currentViewContext instanceof OnTabReselectListener) {
            OnTabReselectListener listener = (OnTabReselectListener) currentViewContext;
            listener.onTabReselect();
            consumed = true;
        }
    }
    return consumed;
}
FrVaBe
  • 47,963
  • 16
  • 124
  • 157
  • What are you using to set as the indicator for the tabs? – Squonk Mar 30 '11 at 15:48
  • @MisterSquonk I'm using a String. See my edit. – FrVaBe Mar 30 '11 at 16:53
  • See my answer for a possible angle to explore. – Squonk Mar 30 '11 at 22:10
  • Nice solution to handling onTouch and the use of the reselect listener. Glad you got it going - something I may come back to if I need to do it in the future. :-) – Squonk Mar 31 '11 at 13:35
  • @FrVaBe : Hi this looks like it has solved the problem but in my case none of the listener is getting called. FYI I am not using TabActivity.I want to close tab when current tab is selected again.but not able to find the method to do that thanks – nishi Apr 26 '12 at 10:37
  • @nishi I have no answer in mind and unfortunately not much time to explore your question. The best thing would be if you past an own question! – FrVaBe Apr 26 '12 at 12:22

4 Answers4

9

You might be able to get this to work by having your TabActivity implement View.onTouchListener and calling setOnTouchListener for each of the tabs...

for (int i = 0; i < tabWidget.getChildCount(); i++) {
    View v = tabWidget.getChildAt(i);
    v.setOnTouchListener(this);
}

Then override onTouch() in your activity...

@Override
public boolean onTouch(View v, MotionEvent event) {

    // Not sure what to do here to identify each tab

    return false;
}

As you can see from the comment in the above, I'm not sure what to do with the View (v parameter) in the onTouch listener to identify which Tab has been touched.

I can confirm it fires whether or not you touch the currently selected tab or one which isn't selected and it doesn't interfere with changing tabs.

Hope it helps.

Squonk
  • 48,735
  • 19
  • 103
  • 135
  • Thanks for this solution possibility. It worked for me. I add the way I finally did it to my question (as I am not allowed to edit your answer). – FrVaBe Mar 31 '11 at 10:14
  • please see the link below, http://stackoverflow.com/questions/9372851/how-to-detecting-a-click-on-an-already-selected-tab-button/17876162#17876162 – Bhavana Vadodariya Jul 26 '13 at 08:11
4

I'm kind of new to Android, but I think I have a nicer workaround for this problem.

First of all (as stated earlier) this code in TabHost.java makes it impossible to listen for a second click on a tab button:

public void setCurrentTab(int index) {
if (index < 0 || index >= mTabSpecs.size()) {
    return;
}

if (index == mCurrentTab) {
    return;
}
...

So start with creating your own subclass of TabHost (com.mydomain.CustomTabHost)

@Override
public void setCurrentTab(int index) {
if (this.getCurrentTab() == index) {
        // User clicked active tab...
    }
    super.setCurrentTab(index);
}

Your tabActivity is looking for a TabHost-component with the id "tabhost". So just change the reference in your layout-xml from TabHost to your new custom class:

<com.yourdomain.CustomTabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent">

(notice the android:id attribute)

/Tommy

Tommislav
  • 66
  • 3
1

No, it's rather impossible. Below is code from TabHost

public void setCurrentTab(int index) {
    if (index < 0 || index >= mTabSpecs.size()) {
        return;
    }

    if (index == mCurrentTab) {
        return;
    }
    ...

You don't have access to mCurrentTab, so the listener isn't even invoked.

But if you really want you can try reflection ( Change private static final field using Java reflection for example)

Community
  • 1
  • 1
pawelzieba
  • 16,082
  • 3
  • 46
  • 72
  • 1
    This is a helpful hint to look at the TabHost code. I just tried to extend a `CustomTabHost` which will notify a `CustomOnTabSelectListener` but now it seems hard to make the TabActivity use this custom TabHost - and I do not want to make too much `Custom` stuff.... +1 for the moment (will accept your answer if no one top's it) – FrVaBe Mar 30 '11 at 16:20
0

I especially work on 2.2 and use ActivityGroup for bundling activities as Fragments are introduced in API 11. So, I don't know about Fragments, but if you are working with ActivityGroup, this works for me:

First,Kudos to MisterSquonk for his "using the OnTouchListener interface idea!!"

1)Make your TabHost static i.e. static TabHost tabhost. In your ActivityGroup, take a static class variable of the same class(ActivityGroup) like static YourActivityGroup activitygroup; and initialize in the onCreate with this and create a method that changes the view and the activity within the same tab. like:

    public void replaceContentView(String activityIdOrTag,Intent activityIntent)
    {                   
      View v= getLocalActivityManager().startActivity(activityIdOrTag,activityIntent)
                    .getDecorView();
    this.setContentView(v);
 }

2)Simply implement OnTouchListener to any of your activities which is included in your ActivityGroup or I recommend, implement to your ActivityGroup.

3) Set an OnTouchListener like

YourTabActivity.tabhost.getCurrentTabView().setOnTouchListener(this)

4) Now in OnTouch(View v,MotionEvent e):

if (e.getAction()==MotionEvent.ACTION_DOWN)
    {
     Intent backToTop = new Intent(this, YourTopLevel.class);
     YourActivityGroup.activitygroup.replaceContentView("YourTopActivity", backToTop);
    }

Hope this helps you. I'm new to android. Any question will be greatly appreciated.

IronBlossom
  • 3,898
  • 3
  • 35
  • 42
  • Thanks for this alternative solution. Unfortunately I can not check it at the moment. If anybody 'likes' it (s)he should feel free to upvote! – FrVaBe Apr 12 '12 at 12:45