Android: TabHost without TabActivity
Asked Answered
F

4

42

I want to create tabs without extending TabActivity. (The reason is that TabActivity cannot handle a custom titlebar as it seems). I have

public class startTab extends Activity {

 @Override
 public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);
        Resources res = getResources();
        LocalActivityManager mlam = new LocalActivityManager(this, false);
        TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
        tabHost.setup(mlam);
        TabHost.TabSpec spec;
        Intent intent;

    intent = new Intent().setClass(this, Show1.class);
    spec = tabHost.newTabSpec("Items").setIndicator("Items", res.getDrawable(R.drawable.items32_ldpi)).setContent(intent);
    tabHost.addTab(spec);

    intent = new Intent().setClass(this, Show2.class);
    spec = tabHost.newTabSpec("Users").setIndicator("Users",res.getDrawable(R.drawable.user32_ldpi)).setContent(intent);
    tabHost.addTab(spec);
}

}

The error I get is

    07-02 07:11:12.715: ERROR/AndroidRuntime(411): 
Caused by: java.lang.IllegalStateException: Activities can't be added until the containing group has been created.

The xml for the view is

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/tabhost" android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent" >
 <LinearLayout android:orientation="vertical"
  android:layout_width="fill_parent" android:layout_height="fill_parent"
  android:paddingTop="5dip">
  <TabWidget android:id="@android:id/tabs"
   android:layout_width="fill_parent" android:layout_height="fill_parent"></TabWidget>
  <FrameLayout android:id="@android:id/tabcontent"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:paddingTop="5dip">
  </FrameLayout>
 </LinearLayout>
</TabHost>

I read somewhere that I have to use a LocalActivityManager, I assume that I am missing something there. Anyone an idea?

Thanks!

Frederiksen answered 2/7, 2010 at 7:15 Comment(1)
this tutorial might help you learnncode.wordpress.com/2013/12/18/…Gulden
C
86

Before calling tabHost.setup(mLocalActivityManager); you need to add this line.

mlam.dispatchCreate(savedInstanceState);
tabHost.setup(mlam );

similarly, you need to add for onResume,

mlam.dispatchResume(); 

onPause(),

 mlam.dispatchPause(isFinishing());
Coly answered 23/2, 2011 at 23:45 Comment(9)
But could you please explain why this works after adding these dispatchXXX() methods? Thanks very much:)Altheaalthee
great!! but any idea why all these extra lines?Tallith
It doesn't work for me.. I'm getting android.util.AndroidRuntimeException: You cannot combine custom titles with other title features. Note that my code is pretty similar as shown in question and I'm using Custom Title feature.Albany
It's an ugly solution. Another alternative is extends ActivityGroup, but the idea is not make the Activity extend strange things just because it has to display tabs. So maybe CommonsWare's answer about using views is the best? But it's a bit annoying to not be able just to use already existing activities...Us
It also doesn't work (or the solution is incomplete, at least). All my tabs are now empty.Us
is it necessary to use dispatchStop() within onStop() and dispatchDestroy() within onDestroy ?Disaccord
according to alvinalexander.com/java/jwarehouse/android/core/java/android/… it is needed, but I've seen a lot of null-pointer exception's due to dispatchDestroy()Disaccord
tnx! it works for me. I lost more time with Google MapsIngulf
Saved me so much time ThanksFendley
S
13

Please consider using Views as the contents of your tabs. Not only will this result in less code, less consumed heap space, less consumed stack space, and lower CPU utilization, it will also get you past this problem. Here are two examples showing this technique.

Sigmon answered 2/7, 2010 at 7:42 Comment(4)
Thanks. But if I don't work with intents how can I have a different menu for each tab?Frederiksen
@paradroid: load a different menu based on the currently active tab.Sigmon
That's the whole point in using an activity - it's a better functional separation.Folketing
@kilaka: Not really. Activities-in-tabs has been deprecated, because Google agrees that it was a bad idea.Sigmon
A
4
public class ScoreboardActivity extends Activity {
    LocalActivityManager mlam;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scoreboard);
        mlam = new LocalActivityManager(this, false);
        mlam.dispatchCreate(savedInstanceState);
        TabHost th = (TabHost) findViewById(android.R.id.tabhost);
        th.setup(mlam);
        th.addTab(th.newTabSpec("Numpad").setIndicator("Numpad").setContent(R.id.tab1));
        th.addTab(th.newTabSpec("CardCount").setIndicator("CardCount").setContent(R.id.tab2));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_scoreboard, menu);
        return true;


    }
    @Override
    protected void onResume(){
        super.onResume();
        mlam.dispatchResume();
    }

    @Override
    protected void onPause(){
        super.onPause();
        mlam.dispatchPause(isFinishing());
    }

}
Ashcraft answered 1/1, 2013 at 15:47 Comment(1)
LocalActivityManager is deprecated nowConfiscate
I
1

Design considerations notwithstanding, the following does not work at all, and the API seems to indicate that setContent(Intent i) is valid. This works when the activity extends TabActivity, however, extending Activity and adding setup() call results in an exception at android.widget.TabHost$IntentContentStrategy.getContentView(TabHost.java:649)

Funny thing is, the LogCat suggests I forgot to call setup()

mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();

Intent tab1Intent = new Intent(this, ActivityOne.class);
Button tab1View = new Button(this);
tab1View.setText("Activity 1");
  mTabHost.addTab(mTabHost.newTabSpec("tab_1").setIndicator(tab1View).setContent(tab1Intent));
Interstate answered 19/8, 2010 at 15:55 Comment(1)
This looks like it should have been a separate question. The issue you're likely running into is that you're not using a TabbedActivity, which means you need to call set up with the ActivityManager, as suggested above. That will then lead you to this issue, unless you dispatch the events to the ActivityManager properly.Paluas

© 2022 - 2024 — McMap. All rights reserved.