1

After searching for a solution I decided to re-ask a question already asked here.

I have a TabHost control, and I need to put it inside other Layout (LinearLayout). I tuck the example that google gives us (http://developer.android.com/resources/tutorials/views/hello-tabwidget.html) and did the same with the only difference that the TabHost is not the root of the layout and the activity class that display the view doesn't extend TabActivity, but Activity

My xml is this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TabHost android:id="@+id/tabhost"
        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:padding="5dp">
            <TabWidget android:id="@android:id/tabs"
                android:layout_width="fill_parent" android:layout_height="53px"
                android:tabStripEnabled="false" android:layout_margin="1px"
                android:background="#222222" />
            <FrameLayout android:id="@android:id/tabcontent"
                android:layout_width="fill_parent" android:layout_height="fill_parent"
                android:padding="5dp" />
        </LinearLayout>
    </TabHost>
</LinearLayout>

and the java class is this:

public class TabsExampleActivity extends Activity {

    TabHost tabHost;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initTabs();

    }


    private void initTabs() {
        Resources res = getResources();                     // Resource object to get Drawables
        tabHost = (TabHost) findViewById(R.id.tabhost);     // The activity TabHost

        TabHost.TabSpec spec;                               // Resusable TabSpec for each tab
        Intent intent;                                      // Reusable Intent for each tab        

        intent = new Intent("eu.pkg.tabsExample.BuildingTabActivity");
        spec = tabHost.newTabSpec("text").setIndicator("",
                          res.getDrawable(R.drawable.tab_text_selector))
                      .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, ClipArtTabActivity.class);
        spec = tabHost.newTabSpec("clipart").setIndicator("",
                          res.getDrawable(R.drawable.tab_clipart_selector))
                      .setContent(intent);
        tabHost.addTab(spec);


        intent = new Intent().setClass(this, FrameSelectorTabActivity.class);
        spec = tabHost.newTabSpec("frame").setIndicator("",
                          res.getDrawable(R.drawable.tab_frame_selector))
                      .setContent(intent);
        tabHost.addTab(spec);



        intent = new Intent().setClass(this, BgSelectorTabActivity.class);
        spec = tabHost.newTabSpec("bg").setIndicator("",
                          res.getDrawable(R.drawable.tab_bg_selector))
                      .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, BuildingTabActivity.class);
        spec = tabHost.newTabSpec("build").setIndicator("",
                          res.getDrawable(R.drawable.tab_build_selector))
                      .setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(4);
    }
}

If I use as base activity the TabActivity, and I use the TabHost as root, then the code works well, I see the tabs... etc.

The issue appears only if I extend Activity and the error is:

04-11 18:53:38.874: ERROR/AndroidRuntime(32539): java.lang.RuntimeException: Unable to start activity ComponentInfo{eu.pkg.tabsExample/eu.pkg.tabsExample.TabsExampleActivity}: java.lang.NullPointerException

The question is: How to host a TabHost inside a LinearLayout?

Edit:

After changing as suggested in comments, the log cat errors are:

04-11 20:52:01.993: ERROR/imdg81(28747): IsShutDownStarted() 04-11 20:52:01.999: ERROR/SensorManager(28747): registerListener 4:gp2a Light Sensor delay:240 04-11 20:52:01.999: ERROR/SensorManager(28747): =======>>>Sensor Thread RUNNING <<<======== 04-11 20:52:02.075: ERROR/imdg81(28747): IsShutDownStarted() 04-11 20:52:02.284: ERROR/LockPatternKeyguardView(28747): Phone is boot completed. so can send broadcast message for music player 04-11 20:52:05.507: ERROR/jdwp(3675): Failed writing handshake bytes: Broken pipe (-1 of 14) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): FATAL EXCEPTION: main 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): java.lang.RuntimeException: Unable to start activity ComponentInfo{eu.pkg.tabsExample/eu.pkg.tabsExample.TabsExampleActivity}: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'? 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.ActivityThread.access$2300(ActivityThread.java:125) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.os.Handler.dispatchMessage(Handler.java:99) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.os.Looper.loop(Looper.java:123) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.ActivityThread.main(ActivityThread.java:4627) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at java.lang.reflect.Method.invokeNative(Native Method) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at java.lang.reflect.Method.invoke(Method.java:521) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at dalvik.system.NativeStart.main(Native Method) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): Caused by: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'? 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.widget.TabHost$IntentContentStrategy.getContentView(TabHost.java:654) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.widget.TabHost.setCurrentTab(TabHost.java:328) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.widget.TabHost.addTab(TabHost.java:213) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at eu.pkg.tabsExample.TabsExampleActivity.initTabs(TabsExampleActivity.java:43) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at eu.pkg.tabsExample.TabsExampleActivity.onCreate(TabsExampleActivity.java:27) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 04-11 20:52:05.609: ERROR/AndroidRuntime(3675): ... 11 more

Community
  • 1
  • 1
Zelter Ady
  • 6,266
  • 12
  • 48
  • 75
  • 2
    Without extending TabActivity you can't create Tab. – kosa Apr 11 '12 at 15:59
  • Are you sure? From where did u get this info? There is any alternative to TabHost that can live inside another layout? – Zelter Ady Apr 11 '12 at 16:05
  • Having tabhost inside linear layout is not an issue (I am doing same), but without extending tabactivity you can't create Tab. – kosa Apr 11 '12 at 16:07
  • From where did u get that info? Some people say they can run such code (tab inside LL), but nobody gives code. – Zelter Ady Apr 11 '12 at 16:11
  • 2
    What is your objection to TabActivity? It inherits from Activity, so it's not like you would lose functionality by switching to it. – Barak Apr 11 '12 at 16:17
  • I have no objection. Just I don't understand why this should be like this. The reason I want to understand is because in the end I need to have a TabHost that has inside another TabHost (I need top tab buttons, some content and bottom tab buttons). If I use TabActivity as base class, may I add another tabHost inside the first one? – Zelter Ady Apr 11 '12 at 16:21
  • i forgot to say: thank you all for your comments. – Zelter Ady Apr 11 '12 at 16:21
  • 3
    [This](http://stackoverflow.com/a/5098774/924149) will fix your error. You can create Tabs without TabActivity like you can use ListView without extending ListActivity. Those classes just makes it simpler. However you may consider using ActionBar Tabs (e.g. ActionBarSherlock for compatibilty) since TabActivity is deprecated – 207 Apr 11 '12 at 16:33
  • @thinksteep : I have never used a TabActivity and all my apps have tabs. I think it works pretty ok. Though I would like to add that, I have not used separate activities for them, just changed the layouts. – Shubhayu Apr 11 '12 at 17:14
  • @Shubhayu, well, you can tweak the API to get what you want (I feel it is hard way when we have something available to use). – kosa Apr 11 '12 at 18:02
  • @207 Please add an answer with your comment to mark it as the answer. The link you gave me contains the answer and works well. Thank you. – Zelter Ady Apr 11 '12 at 19:38
  • @Zelter Ady Done. You're welcome – 207 Apr 12 '12 at 20:21

4 Answers4

6

Problem solved. The correct solution, as given by the user 207 in one of the comments, from another stackoverflow question is this:

This is the XML:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TabHost android:id="@android:id/tabhost"  
        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:padding="5dp">
            <TabWidget android:id="@android:id/tabs"
                android:layout_width="fill_parent" android:layout_height="53px"
                android:tabStripEnabled="false" android:layout_margin="1px"
                android:background="#222222" />
            <FrameLayout android:id="@android:id/tabcontent"
                android:layout_width="fill_parent" android:layout_height="fill_parent"
                android:padding="5dp" />
        </LinearLayout>
    </TabHost>
</LinearLayout>

and java file:

package eu.pkg.tabsExample;

import android.app.Activity;
import android.app.LocalActivityManager;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TabHost;

public class TabsExampleActivity extends Activity {

    TabHost tabHost;
    LocalActivityManager mLocalActivityManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initTabs(savedInstanceState);
    }

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

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

    private void initTabs(Bundle savedInstanceState) {
        Resources res = getResources();                     // Resource object to get Drawables
        tabHost = (TabHost) findViewById(android.R.id.tabhost);     // The activity TabHost
        mLocalActivityManager = new LocalActivityManager(this, false);
        mLocalActivityManager.dispatchCreate(savedInstanceState);
        tabHost.setup(mLocalActivityManager);

        TabHost.TabSpec spec;                               // Resusable TabSpec for each tab
        Intent intent;                                      // Reusable Intent for each tab        

        intent = new Intent("eu.pkg.tabsExample.BuildingTabActivity");
        spec = tabHost.newTabSpec("text").setIndicator("",
                          res.getDrawable(R.drawable.tab_text_selector))
                      .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, ClipArtTabActivity.class);
        spec = tabHost.newTabSpec("clipart").setIndicator("",
                          res.getDrawable(R.drawable.tab_clipart_selector))
                      .setContent(intent);
        tabHost.addTab(spec);


        intent = new Intent().setClass(this, FrameSelectorTabActivity.class);
        spec = tabHost.newTabSpec("frame").setIndicator("",
                          res.getDrawable(R.drawable.tab_frame_selector))
                      .setContent(intent);
        tabHost.addTab(spec);



        intent = new Intent().setClass(this, BgSelectorTabActivity.class);
        spec = tabHost.newTabSpec("bg").setIndicator("",
                          res.getDrawable(R.drawable.tab_bg_selector))
                      .setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, BuildingTabActivity.class);
        spec = tabHost.newTabSpec("build").setIndicator("",
                          res.getDrawable(R.drawable.tab_build_selector))
                      .setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(4);
    }
}

the magic behind the scene is in those 4 lines of code:

    tabHost = (TabHost) findViewById(android.R.id.tabhost);     // The activity TabHost
    mLocalActivityManager = new LocalActivityManager(this, false);
    mLocalActivityManager.dispatchCreate(savedInstanceState);
    tabHost.setup(mLocalActivityManager);

Thank you all for contribution to this answer.

Zelter Ady
  • 6,266
  • 12
  • 48
  • 75
0

Here is the solution if you are using Activity instead of extending TabActivity

https://stackoverflow.com/a/5098774/563306

Community
  • 1
  • 1
dcanh121
  • 4,665
  • 11
  • 37
  • 84
0

Change this particular line

TabHost android:id="@+id/tabhost"

to

TabHost android:id="@android:id/tabhost"

EDIT

Also add after the following line

tabHost = (TabHost) findViewById(R.id.tabhost);
tabHost.setup();
Shubhayu
  • 13,402
  • 5
  • 33
  • 30
  • I changed now like this: and in java like this: private void initTabs() { Resources res = getResources(); // Resource object to get Drawables tabHost = (TabHost) findViewById(android.R.id.tabhost); // The activity TabHost tabHost.setup(); TabHost.TabSpec spec; // Resusable TabSpec for each tab Intent intent; // Reusable Intent for each tab ///......... the rest of the code – Zelter Ady Apr 11 '12 at 17:41
  • can u add the complete logcat? – Shubhayu Apr 11 '12 at 17:48
  • I edit the original post to add the log. see it on top of the page. – Zelter Ady Apr 11 '12 at 17:53
  • Can you try by excluding the first tab? and see if it works? dont include this intent = new Intent("eu.pkg.tabsExample.BuildingTabActivity"); spec = tabHost.newTabSpec("text").setIndicator("", res.getDrawable(R.drawable.tab_text_selector)) .setContent(intent); tabHost.addTab(spec); – Shubhayu Apr 11 '12 at 18:00
  • Ya saw it :) I learnt a new thing about managing intents in the Tabs. Didnt know about that earlier. – Shubhayu Apr 12 '12 at 16:21
0

This will fix your error.

In addition: I just read that you want to extent from Activity instead of TabActivity because you're trying to achieve "nested tabs". It sould not be a problem having a TabActivity within another TabActivity. Haven't done this before but I don't see any troubles that may come off. There is no difference in adding an Activity or TabActivity as tab content. You may give it a try

Community
  • 1
  • 1
207
  • 3,784
  • 2
  • 25
  • 22