XML layout in tab android (tabhost) - android

I'm trying to get a tabbed layout working on android. Using an example I managed to get the tabs working but my different tabs are in different activities. Each tab is similar, it's almost the same so I want them in the same activity.
I want an xml file in the layout folder as content.
This works, seperate classes:
tabSpec1.setIndicator("tabName1").setContent(new Intent(this, FirstTab.class));
This doesn't work:
tabSpec2.setIndicator("tabName2").setContent(R.layout.tab);
The setContent function accepts id's like that. The reference to tab is also in my R class. This is the XML in my tab:
<?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">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is the tab from XML"/> </LinearLayout>

Check this: unable to add views in TabHost by IDs, crashing
If you want to set content of each tab by View ids, you have to make sure that there is some layout xml that defines TabHost, TabWidget, and FrameLayout tags properly. Then the views that you want to be set by ids can be put as child tags in FrameLayout. Without any one of the tags mentioned above, the app will crash due to "cannot find view id xxxxxx".
You can get what you want by combining this and the <include> tag.

There are a couple of ways to do this. One way is to add a view like Cephron has shown in another answer.
Depending on how similar the tab activities are. Another way to do this would be to pass the intent to the same activity with different extras and then parse them in the Activity code.
Something like:
Intent intent = new Intent(this, FirstTab.class);
intent.putExtra("callingTab", 1);
tabSpec1.setIndicator("tabName1").setContent();
You activity code can then use something like this:
if (FirstTab.this.getIntent().getExtras() != null) {
callingTab = this.getIntent().getExtras().getInt("callingTab");
}
This will allow you to use the same layout for both activities with the minor changes you require coded in.

I think what you need is to have Views, not activities, in each tab. Try something like this...
In the tab activity:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_page_layout);
//Setting up TabWidget
Resources res = getResources();
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
spec = tabHost.newTabSpec("firstTab")
.setIndicator(res.getString(R.string.tab1_label), res.getDrawable(R.drawable.tab1_icon))
.setContent(R.id.tab1_layout);
tabHost.addTab(spec);
spec = tabHost.newTabSpec("secondTab")
.setIndicator(res.getString(R.string.tab2_label), res.getDrawable(R.drawable.tab2_icon))
.setContent(R.id.tab2_layout);
tabHost.addTab(spec);
tabHost.setCurrentTab(0);
}
In the tab_page_layout.xml file:
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:id="#+id/tab1_layout"
/>
<!--your stuff-->
</LinearLayout>
<LinearLayout android:id="#+id/tab2_layout"
/>
<!--your stuff-->
</LinearLayout>
</FrameLayout>
(The above is just a fragment, of course. You'll still need to include the TabWidget and use the appropriate identification)

Related

adding views to tab Vs adding activities to tab android

I am designing tabs in my app. I am confused whether to use activities for tab or just use views
which one is the better way for tablayout
I am confused ..
I am bit new to tabs and still learning tab layout in android, so my question can be a little naive so please bear with it :)
To answer your question of "activity or view in a tab layout"
This is what the android tutorial sais:
You can implement your tab content in one of two ways: use the tabs
to swap Views within the same Activity, or use the tabs to change
between entirely separate activities. Which method you want for your
application will depend on your demands, but if each tab provides a
distinct user activity, then it probably makes sense to use a separate
Activity for each tab, so that you can better manage the application
in discrete groups, rather than one massive application and layout.
Android tablayout tutorial
I highly recommend following the tutorial, then try to implement your own version for your app.
Here is a code sample just in case;
public class TabHostExample extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testtabs);
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
Intent content;
spec = tabHost.newTabSpec("test1"); //set a title for the tab
spec.setIndicator("test1"),
getResources().getDrawable(R.drawable.ic_dialog_alert)); //set an icon for tab
content = new Intent(this, ExampleActivityOne.class);
spec.setContent(content);
tabHost.addTab(spec);
spec = tabHost.newTabSpec("test2")); //set a title for the tab
spec.setIndicator("test2"),
getResources().getDrawable(R.drawable.ic_dialog_info)); //set an icon for the tab
content = new Intent(this, ExampleActivityTwo.class);
spec.setContent(content);
tabHost.addTab(spec);
tabHost.setCurrentTab(0);
}
}
<TabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#android:id/tabhost">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TabWidget
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#android:id/tabs"
/>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#android:id/tabcontent"
/>
</LinearLayout>
</TabHost>
A bit of extra information from the tutorial:
The framelayout is where the content of the activity per tab goes.
Notice that the TabWidget and the FrameLayout elements have the IDs tabs and tabcontent, respectively. These names must be used so that the TabHost can retrieve references to each of them. It expects exactly these names.
So with this code you have a basic setup for a tab layout, what you do next is, attach an activity to a tab. You use the activity like normal, for these activities you extend Activity as you normally would for an activity and build your layout in onCreate/onResume
If you need more information or more explanation please leave a comment. I think most code is self explanatory though.
I just noticed my code is almost an exact copy from the tutorial page.
I actually use this code in my app, with different names for the activities etc. It works great. I recommend it. Credits goes to the Android team.
You have to use activities. Every tab has activity. There are good tutorials at developer.android.com Try this one here
Try Activities..Look for TabActivity which is best way to deal the TABS in an App.. http://developer.android.com/reference/android/app/TabActivity.html and http://developer.android.com/resources/tutorials/views/hello-tabwidget.html

Android 1.6 TabHost inside a Fragment

In the demo Support4Demos - API 4+ Support Demos , the Tabs and TabsPager examples both extend FragmentActivity. Each tab content is itself a Fragment. No real breakthrough, TabActivity was used the same way without the introduction of Fragment.
Now suppose inside my Activity , a screen portion is a Fragment named WidgetFragment. How is it possible for WidgetFragment to contain a TabHost ? Visualize a mini TabHost contained inside an Activity.
I tried every possible way to insert a TabHost inside a Fragment not a FragmentActivity.
In generally accepted practices, Tabs fit the whole screen.
Most people (including me) are unaware the tabs can be placed anywhere like a simple view, ListView.
The trick is to include your TabHost inside another layout. When you create the TabHost, always keep these id : tabhost , tabs , tabcontent
In your main layout, include your tabhost.xml . Here I center the TabHost in the middle
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!-- Fill whatever you need -->
<FrameLayout
android:id="#+id/widget_fragment"
android:layout_centerVertical="true" android:layout_centerHorizontal="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<include layout="#layout/tabhost" />
</FrameLayout>
</LinearLayout>
Look well at the Tabs and TabsPager examples in Support4Demos , the TabHost is still managed by FragmentActivity. Each tab content is a fragment. With TabActivity, it may not be possible to have a tab anywhere
At the end, this is what it looks like

Alternatives to using an activity for each tab

The scenerio is like this. Currently I am using the following code
TabSpec setContent = tabhost.newTabSpec("tab")
.setIndicator("tabview")
.setContent(new Intent(tabhost.getContext(), someActivity.class));
But I am told that each tab should not be associated with an activity and we must follow code something like this.
TabSpec setContent = tabhost.newTabSpec("tab").setIndicator("tabView").setContent(R.id.layout)
Consider a scenario where tab1 calls camera app, tab2 parses an XML and tab3 does some other display work. How do I solve this ? Because as soon as tab is changed I must call these methods. How do I create a single activity and assign all responsibilities to it ?
You can create a single activity with tabs that show only views. The only catch is that the views have to be defined inside the tag.
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#+id/list1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<ListView
android:id="#+id/list2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</FrameLayout>
Then, when inside your onCreate in your TabActivity:
TabHost tabs = getTabHost();
TabHost.TabSpec commentsTab = tabs.newTabSpec(TAB_TAG_1);
tabs.addTab(commentsTab.setContent(R.id.list1));
TabHost.TabSpec infoTab = tabs.newTabSpec(TAB_TAG_2);
tabs.addTab(infoTab.setContent(R.id.list2));
Note that I did not specify indicators for either tab, in the interests of space.

Android Tabs in Bottom of the Layout [duplicate]

I've seen some chatter about this, but nothing definite.
Is there a way to put the tabs in a TabWidget to the bottom of the screen?
If so, how?
I've tried the following, but didn't work:
a) setting the tabwidget below the framelayout
b) setting the tabwidget's gravity to "bottom"
Thanks!
llappall
Here's the simplest, most robust, and scalable solution to get tabs on the bottom of the screen.
In your vertical LinearLayout, put the FrameLayout above the TabWidget
Set layout_height to wrap_content on both FrameLayout and TabWidget
Set FrameLayout's android:layout_weight="1"
Set TabWidget's android:layout_weight="0" (0 is default, but for emphasis, readability, etc)
Set TabWidget's android:layout_marginBottom="-4dp" (to remove the bottom divider)
Full code:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
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">
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_weight="1"/>
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_marginBottom="-4dp"/>
</LinearLayout>
</TabHost>
Try it ;)
Just watch the content of the FrameLayout(#id/tabcontent), because I don't know how it will handle in case of scrolling... In my case it works because I used ListView as the content of my tabs. :)
Hope it helps.
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_above="#android:id/tabs" />
<TabWidget android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</TabHost>
There is a way to remove the line.
1) Follow this tutorial:
android-tabs-with-fragments
2) Then apply the RelativeLayout change that Leaudro suggested above (apply the layout props to all FrameLayouts).
You can also add an ImageView to the tab.xml in item #1 and get a very iPhone like look to the tabs.
Here is a screenshot of what I'm working on right now. I still have some work to do, mainly make a selector for the icons and ensure equal horizontal distribution, but you get the idea.
In my case, I'm using fragments, but the same principals should apply to a standard tab view.
Not sure if it will work for all versions of Android (especially those with custom UI stuff), but I was able to remove the gray bar at the bottom by adding
android:layout_marginBottom="-3dp"
to the TabWidget XML...
For all those of you that try to remove the separating line of the tabWidget, here is an example project (and its respective tutorial), that work great for customizing the tabs and thus removing problems when tabs are at bottom.
Eclipse Project: android-custom-tabs ;
Original explanation: blog;
Hope this helped.
There are two ways to display tabs at the bottom of a tab activity.
Using relative layout
Using Layout_weight attribute
Please check the link for more details.
This may not be exactly what you're looking for (it's not an "easy" solution to send your Tabs to the bottom of the screen) but is nevertheless an interesting alternative solution I would like to flag to you :
ScrollableTabHost is designed to behave like TabHost, but with an additional scrollview to fit more items ...
maybe digging into this open-source project you'll find an answer to your question. If I see anything easier I'll come back to you.
I was having the same problem with android tabs when trying to place them on the bottom of the screen. My scenario was to not use a layout file and create the tabs in code, I was also looking to fire activities from each tab which seemed a bit too complex using other approaches so, here is the sample code to overcome the problem:
adding-tabs-in-android-and-placing-them
Yes, see: link, but he used xml layouts, not activities to create new tab, so put his xml code (set paddingTop for FrameLayout - 0px) and then write the code:
public class SomeActivity extends ActivityGroup {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TabHost tab_host = (TabHost) findViewById(R.id.edit_item_tab_host);
tab_host.setup(this.getLocalActivityManager());
TabSpec ts1 = tab_host.newTabSpec("TAB_DATE");
ts1.setIndicator("tab1");
ts1.setContent(new Intent(this, Registration.class));
tab_host.addTab(ts1);
TabSpec ts2 = tab_host.newTabSpec("TAB_GEO");
ts2.setIndicator("tab2");
ts2.setContent(new Intent(this, Login.class));
tab_host.addTab(ts2);
TabSpec ts3 = tab_host.newTabSpec("TAB_TEXT");
ts3.setIndicator("tab3");
ts3.setContent(new Intent(this, Registration.class));
tab_host.addTab(ts3);
tab_host.setCurrentTab(0);
}
}
I recomend use this code for stable work, it optimized for nested fragments in tab (for example nested MapFragment) and tested on "do not keep activities": https://stackoverflow.com/a/23150258/2765497

How to add controls to a Tab Layout in Android?

I am following this tutorial https://developer.android.com/guide/tutorials/views/hello-tabwidget.html and have completed it. Now I would actually like to add you know some controls to these tabs like textboxes(text edit).
How do I do this? I go to my mail.xml using eclipse as my ide and go to layout view and I now get a NullPointerException so I can't even drag stuff onto the layout anymore.
Edit
This is what I have
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
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">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a tab" />
<EditText android:text="" android:id="#+id/EditText01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:password="true"></EditText>
</LinearLayout>
<TextView
android:id="#+id/textview2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is another tab" />
<TextView
android:id="#+id/textview3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a third tab" />
</FrameLayout>
</LinearLayout>
</TabHost>
Tabs are a bit funny to get working initially since there's a lot of code overhead, but once you've worked your way through that they aren't too bad. To get tabs to work, let's start by improving your XML file and then we can make sure your code to actually load them is correct.
First off, your XML file. Instead of including everything directly in your main.xml, you should use the include feature. As the name would suggest, this lets you work on a separate xml file and then include it in your main with one line. This makes the main.xml file much easier to read. So we'd modify your file above to make it look like this:
//No need to change anything above this
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout="#layout/tab1"/>
<include layout="#layout/tab2"/>
//and however many other tabs you want to include
</FrameLayout>
You then need to create tab1.xml, tab2.xml and so forth. These are normal xml files in that they start with a ViewGroup (i.e. LinearLayout, RelativeLayout) which contains any number of other widgets. These widgets can be things like EditTexts, buttons, custom views, whatever you want. The only rule is that the parent ViewGroup (the one at the top) must have a unique ID in it, in the manner of android:id="#+id/someUniqueName". You will use that to refer to that specific layout/tab in your code. So for example, this would be:
tab1.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/tab1Layout"
android:orientation="vertical">
<TextView ... />
<EditText ... />
</LinearLayout>
With that done, we can look at your code. I assume you've probably already got this, but just in case here's what you want:
public class YourProject extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Resources res = getResources();
TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("Tab1 title",
res.getDrawable(R.drawable.logo1)).setContent(R.id.tab1Layout));
(...)
//You can also fill tabs with a separate activity like so:
Intent intent = new Intent(this, YourClass.class);
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("Another title",
res.getDrawable(R.drawable.logo2)).setContent(intent));
tabHost.setCurrentTab(0);
}
}
As shown above you can set the content of one of the tabs to be a separate activity. In that case, the activity is defined just as any other one with its own Class, layout, etc. Usually you shouldn't do this and instead just use a different View (with setContent(R.id.tabXLayout), but sometimes it's needed. For example if you want one of your tabs to have a list, then you need to start an activity in there that extends ListView, and include all the boilerplate code for ListViews.
I hope that helps!
The layout view in Eclipse can be a bit flaky, particularly with complex layouts. A bit of trial and error might find the View node it is choking on.
As regards developing the tab-based layout further, you have two options, the 'quick' way or the 'right' way. First is to adapt the existing layout xml by replacing one of the TextViews with a LinearLayout (or some other layout) which contains the content you want.
http://google.com/codesearch/p?hl=en#HQNWZ1u2Pig/trunk/HelloLayoutAndroid/res/layout/tab_widget.xml
However Tabs are generally used where there is complex content. For scalability it may be better to locate the TabHost in the layout, call newTabSpec() and then use setContent() to supply an Intent that identifies an internal Activity, which supplies its own Layout.
the include often makes problems while parsing XML, I tried it and got :cannot resolve #layout/mylayout..
my code was correct 100%, but it's common problem spicialy if you need Id for the layout and other attributes.
samply: I solve it by the disign mode, when you drop tabhost to your layout, place it wherever you want, it creates 3 Linear layouts (tab1,tab2,tab3)... on XML editor, in each tab (leanearlayout) insert your markup of the control you need to use as content of the tab.
and in java file do the next:
TabHost tabHost = (TabHost)findViewById(R.id.tabHost);
tabHost.setup();
TabHost.TabSpec tab1 = tabHost.newTabSpec("smil1");
TabHost.TabSpec tab2 = tabHost.newTabSpec("smil2");
TabHost.TabSpec tab3 = tabHost.newTabSpec("smil3");
tab1.setIndicator("#1");//the name will apear on the first tab
tab1.setContent(R.id.smiles1); // the Id of the control you put in the first LeanerLayout
tab2.setIndicator("#2"); // the same as abouv but for the second tab
tab2.setContent(R.id.smiles2);
tab3.setIndicator("#3"); // the thierd tab
tab3.setContent(R.id.smiles3);
// add the tabs
tabHost.addTab(tab1);
tabHost.addTab(tab2);
tabHost.addTab(tab3);
this is the way solving your problem if include makes problem in parsing your XML.
The NullPointerException in the layout editor is a known bug in the Android Development Tools.

Categories

Resources