January 30, 2015

Tabs With Intents

If you look at the Android widgets and classes related to tabs, you’ll see that a tab can have either a View or an Activity as its contents. Most of the time, people use Views, as they are simpler to implement and lighter-weight to run. However, there may be circumstances where you feel putting your activities in tabs would be useful, so let’s take a look at how that is done, in a modified excerpt from Version 1.9 of The Busy Coder’s Guide to Android Development.

If you want to use an Activity as the content of a tab, you provide an Intent that will launch the desired Activity; Android’s tab-management framework will then pour the Activity’s user interface into the tab. So, let’s create a tabbed Web browser.

Your natural instinct might be to use an http: Uri as the target of the Intents, one Intent per tab. That way, you could use the built-in Browser application and get all of the features that it offers. Alas, this does not work. It appears you cannot host other applications’ activities in your tabs, only your own activities, presumably for security reasons.

But, we can always use the WebView widget to provide a simplified browsing experience.

Here is the source to the main activity, the one hosting the TabView:

[sourcecode language=”java”]
public class IntentTabDemo extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

TabHost host=getTabHost();

host.addTab(host.newTabSpec(“one”)
.setIndicator(“CW”)
.setContent(new Intent(this, CWBrowser.class)));
host.addTab(host.newTabSpec(“two”)
.setIndicator(“Android”)
.setContent(new Intent(this, AndroidBrowser.class)));
}
}
[/sourcecode]

As you can see, we are using TabActivity as the base class, and so we do not need our own layout XML — TabActivity supplies it for us. All we do is get access to the TabHost and add two tabs, each specifying an Intent that directly refers to another class. In this case, our two tabs will host a CWBrowser and an AndroidBrowser, respectively.

Those latter two activities are simple wrappers around WebView:

[sourcecode language=”java”]
public class CWBrowser extends Activity {
WebView browser;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

browser=new WebView(this);
setContentView(browser);
browser.loadUrl(“http://commonsware.com”);
}
}
[/sourcecode]

[sourcecode language=”java”]
public class AndroidBrowser extends Activity {
WebView browser;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

browser=new WebView(this);
setContentView(browser);
browser.loadUrl(“http://code.google.com/android”);
}
}
[/sourcecode]

They simply load a different URL into the browser: the CommonsWare home page in one, the Android home page in the other.

The resulting UI shows what tabbed browsing could look like on Android:

Using distinct subclasses for each targeted page is rather wasteful. Instead, we could have packaged the URL to open as an “extra” in an Intent and used that Intent to spawn a general-purpose BrowserTab activity, which would read the URL out of the Intent “extra” and use this. The proof of this is left as an exercise for the reader.



131 Comments

  1. haden

    One more question.
    Say I have a tab called A
    I have an activity displayed on it on Tab A

    How do i display a new activity on Tab A without leaving the tab View?

    i.e. How do I launch a new activity within the current Tab?

  2. haden

    It’s a real shame.Android should have provided a method of launching activities within a tab.Thanks anyway

  3. Spoony

    IN RESPONSE TO THE ABOVE:

    YES, sure its very possible.

    Instead of
    this.startActvity(…)
    use
    this.getLocalActivityManager().startActivity(…)

  4. r45k

    I can’t seem to run that code… nor any code similar to that for that matter…

    Can anyone confirm this code still works for the SDK v1.1?

  5. Mark Murphy

    @r45k:

    The code worked for me a week or two ago on the 1.1r1 SDK.

    Visit the CommonsWare site and download the source code to my book. You’ll find the above code in a complete project (Activities/IntentTabs). Try that and see if it works for you.

    If not, join the [cw-android] Google Group and post your symptoms, and I can look into the problem.

  6. Cybran

    didn’t work for me either

    no compiler errors but when i run in the emulator i get the following error message:

    “The application Tabs with Intents (process com.android.test) has stopped unexpectedly. Please try again”

    This is happening on SDK v1.1

    cheers

  7. Sujay

    Hello Mark…

    Even I am facing the same issue… Please lemme know how to tackle it… No Compilation errors … No Warnings… Simply.. the app fails to execute…

  8. Mark Murphy

    The code shown in this blog post is not ALL the code you need to run the application. For example, you need to add your two in-tab activities to your AndroidManifest.xml file.

  9. Mark Murphy

    Aha! My comment-posting problems seem to be when I include a URL. So, let’s try a more elaborate reply…

    The code shown in this blog post is not ALL the code you need to run the application. For example, you need to add your two in-tab activities to your AndroidManifest.xml file.

    A complete version of this project can be found in the source code for my Android book — visit http://commonsware.com/Android/ and scroll down to the Source Code link. In the ZIP file, you will find Activities/IntentTabs that contains the complete project.

  10. Sujay

    Hello Mark…

    Thanks for the reply…

    I did download that source code and tried running the project that youve provided… it dint workout… it didnt run either… :(

  11. Mark Murphy

    @Sujay:

    I just ran it here, and it works just fine. I suspect there is some other problem with your environment.

  12. Sujay

    Hello Mark;

    Reinstalled the whole environment!!!

    Problem Solved…. Thanks a lot for support…

    I am developing a downloader based app…. U have any resources to refer and you could point me to?? Would be of great Help for me…

    Regards n Best Wishes

  13. Mark Murphy

    @Sujay:

    Glad you got it working!

    I am not sure what a “downloader based app” is. I would recommend you post your query to the [android-developers] Google Group, anddev.org, or the Android board at JavaRanch. Be sure to describe in somewhat greater detail what it is you are trying to do or need assistance with.

  14. Sujay

    Hello Mark;

    Thnaks for the great suggestion last time…

    Ive built the app halfway…

    Now my problem is… the user is forced to use the search feature which has been implmented using html and php ….. which further yeilds the download result and download link…

    Everything works fine untill user searches for the keywords…. but the search results are displayed in a new browser window…. and it escapes out of my actual application.
    The same happens even when i try to open a hyperlink… how do i keep the whole process contained within that tab??

    My whole aplication would require the webpage in these stages..

    1-> On Application start; it will show the search page in the search tab and allow user to search…

    2-> It must show the search results and download link within the tab…. ( Here it escapes it of the app… and opens the browser)

    3-> On clicking on the download link…. the downloader is invoked… ( Here ill be forcing my downloader function to take control)

    Currently my aim is to keep the stage 2 within the tab….
    Help will be much appreciated….

    Regards;
    Sujay

  15. achim

    Hi, nice tutorial!

    I followed the example, then made one of the child activities (e.g. CWBrowser) display a dialog using showDialog(). Now if I rotate the device, the dialog disappears and is not re-created, although dialogs of the parent activity (e.g. IntentTabDemo) are re-created.

    Anyone else experiencing this problem? Any ideas on how to solve it?

  16. Наум

    Читал про это уже на каком то другом сайте, но у вас гораздо прикольней написано ;)

  17. Joe

    Hey Mark,

    doesnt think open the URL in a new view?

    Ive followed this and while it did infact load a page when that tab was selected, it was not in the view within the tab, it was a new window and not as show in your pics.

    Any Idea what could be causing this?

    many thanks

  18. Anne

    Is possible to have the tabs used in USAtoday app with the control tab???

  19. Profete162

    Just a question:

    What is the beast and easiest way to add an icon to the tab?

    Thank a lot for any clue/answer

  20. saya

    I can't seem to run that code.Is there any code to add to the manifest to work this code

  21. question

    @saya: The activities (intents) need to be added to the manifest.

  22. question

    @Profete162:

    Resources res = getResources();
    spec = tabHost.newTabSpec("Items").setIndicator("Items", res.getDrawable(R.drawable.items48_mdpi)).setContent(intent);

  23. AJ Quick

    Can anyone get the back button to work with this? I setup a way to do it and it crashes the app every time the back button is pressed. I want it to go back to a previous page.

  24. CB

    Thanks for posting this tutorial. Once I figured out that I needed to update the manifest, I got it running. I’ve got two questions:
    (1) Originally I put the small Activity classes inside the main IntentTab class. I though if I did that I didn’t need to declare it in the manifest. Is that not true? Or is nesting an Activity class inside another a no-no?
    (2) Now that the app is running, when I select the Android Browser tab it kicks off a browser window seperate from the IntentTab app. That doesn’t appear to be the expected result from your screen shots above.

    Thanks!