For my app, I am trying to put buttons at the bottom of all activities similar to WeChat app as can be seen in below image:
Now one way I thought of is simply adding <ImageButton>s at bottom of each activities but I don't think WeChat does that because you can swipe between activities and there is no onCreate triggered, activities are always there that are simply switched when swiped or touched on specific button.
I did research and found out one can use split action bar or even ViewFlipper. Action bar splitting is out of question since button will be moved back to action bar for example in landscape mode since I want to have buttons always appear at bottom like WeChat. Another option I saw was Tabbed interface but I saw with it, it can appear below actionbar unlike WeChat where even actionbar is changed based on activity.
Question: Does anyone know what does WeChat use for this functionality so I can implement the same ?
here is code main class
public class TabSample extends TabActivity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setTabs();
}
private void setTabs() {
addTab("Wechat", R.drawable.tab_home, ShowList.class);
addTab("Social", R.drawable.tab_search, UploadVideo.class);
addTab("Contact Us", R.drawable.tab_home, Contactus.class);
addTab("Setting", R.drawable.tab_search, DoNotDo.class);
}
private void addTab(String labelId, int drawableId, Class<?> c) {
TabHost tabHost = getTabHost();
Intent intent = new Intent(this, c);
TabHost.TabSpec spec = tabHost.newTabSpec("tab" + labelId);
View tabIndicator = LayoutInflater.from(this).inflate(
R.layout.tab_indicator, getTabWidget(), false);
TextView title = (TextView) tabIndicator.findViewById(R.id.title);
title.setText(labelId);
ImageView icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageResource(drawableId);
spec.setIndicator(tabIndicator);
spec.setContent(intent);
tabHost.addTab(spec);
}
}
here is xml
<?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:background="#ffffff"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_weight="0" />
</LinearLayout>
</TabHost>
One Idea is create BaseActivity, in which include the general design you prefer throughout the App. In other activities, extend BaseActivity. You can also extend Activity class in some activities where no need to show the buttons, such as LoginActivity.
Related
My Tab_Bar.class define define Tabs
How I can open child activity
I am using only one single Tab_bar.class for Tab Host
public class Tab_Bar extends TabActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab);
setTabs() ;
}
void setTabs()
{
addTab("My Profile", R.drawable.home_normal, MyProfile.class);
addTab("Search", R.drawable.search_normal, JobSearch.class);
addTab("Saved Jobs", R.drawable.starred, Saved_jobs.class);
addTab("Job Alert", R.drawable.job_match, JobAlert.class);
}
private void addTab(String labelId, int drawableId, Class<?> c)
{
TabHost tabHost = getTabHost();
Intent intent = new Intent(this, c);
TabHost.TabSpec spec = tabHost.newTabSpec("tab" + labelId);
View tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator, getTabWidget(), false);
TextView title = (TextView) tabIndicator.findViewById(R.id.title);
title.setText(labelId);
ImageView icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageResource(drawableId);
spec.setIndicator(tabIndicator);
spec.setContent(intent);
tabHost.addTab(spec);
tabHost.setCurrentTab(1);
}
}
I am using these xml file
TabIndicator.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dip"
android:layout_height="55dip"
android:layout_weight="1"
android:orientation="vertical"
android:background="#drawable/tab_indicator"
android:padding="5dp">
<ImageView android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="#drawable/icon"
/>
<TextView android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
style="?android:attr/tabWidgetStyle"
android:textSize="13sp"
/>
and Tab.xml
<?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">
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="fill_parent" android:layout_height="0dip"
android:layout_weight="1" />
<TabWidget android:id="#android:id/tabs"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="0" />
</LinearLayout>
</TabHost>
I am using Tab_bar.class and these xml file for Tab host but i can't have any idea about open
tab host child activity .
I am new in android.
Please Help me, How i can open child activity
Any Help is Appreciated
And I am really sorry about my bad English
This is not eaxctly what you need, but might help. I used this setup to create dynamic tabs and then do different things with them.
protected void onCreate(Bundle savedInstanceState) {
...
final TabHost Tabs = (TabHost) findViewById(android.R.id.tabhost);
Tabs.setup();
int count;
for (count =0;count < 2;count++){
...
final int passedTabId = count;
NewTab.setContent(new TabHost.TabContentFactory()
{
public View createTabContent(String tag)
{
...
RelativeLayout layout = new RelativeLayout(getApplicationContext);
android.widget.RelativeLayout.LayoutParams params =
new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
layout.setLayoutParams(params);
layout.setId(some ID);
layout.setBackgroundResource(R.drawable.room_background);
TextView dynText = new TextView(getApplicationContext);
...
layout.addView(dynText);
return layout;
// You can set onClickListeners, etc here and then assign them some functions you need
// You can also create different layouts for every tab according to the passedTabId
}
});
Tabs.addTab(NewTab);
}
}
Thing is, you cant just simply set another activity to run in each tab. You need to set some functions you need to the objects you create in that tab, but the main activity remains the same. Good luck :)
Firstly try using Fragment for creating tabs.
Feature which you are using is deprecated by now.
I have posted complete post over Dynamically changing the fragments inside a fragment tab host?
Please check that out and let me know if you have any concern.
Simply fallow each of defined steps one by one.
CONCEPT
I am putting simple example for clarifying you that exactly how this fragment works.
Take simple scenario of your bed. Your bed consist of several things such as pillow, bed sheet etc.
Now consider a case that your bed sheet is dirty. So what you will do by now. You will simply replace that sheet with a new one and then you will have a tight sleep :)
Similarly when you need to change your UI... then this fragment is replaced with a new one.
That's it. Now you are good to go with my post.
Thanks!
I am developing an application using android 2.1. In one Page, upper part have two textviews and lower part have tablayout having two tabs.
My XML code is like this...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<include android:id="#+id/content" layout="#layout/content_table"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tabHost" android:layout_below="#+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<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="wrap_content" />
</LinearLayout>
</TabHost>
</RelativeLayout>
And activity class is like...
public class PageActivity extends ActivityGroup {
LogoBarActivity logoBar;
TabHost mTabHost;
TextView text1;
TextView text2;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.page);
text1 = findViewById(R.id.textview1);
text2 = findViewById(R.id.textview2);
mTabHost = (TabHost) findViewById(R.id.tabHost);
mTabHost.setup(this.getLocalActivityManager());
TabHost.TabSpec spec;
Intent intent;
intent = new Intent().setClass(this, Type1Activity.class);
spec = mTabHost.newTabSpec("type1").setIndicator("Type1").setContent(intent);
mTabHost.addTab(spec);
intent = new Intent().setClass(this, Type2Activity.class);
spec = mTabHost.newTabSpec("type2").setIndicator("Type2").setContent(intent);
mTabHost.addTab(spec);
mTabHost.setCurrentTab(0);
mTabHost.getTabWidget().getChildAt(0).getLayoutParams().height /= 2;
mTabHost.getTabWidget().getChildAt(1).getLayoutParams().height /= 2;
}
}
Explanation: When user comes this page, he can click on any tabs either on Type1 or Type2. Both Tabs have ListView (Type1Activity & Type2Activity are ListView ).
When user click on any tab he will get ListView in Tabs. User can select any item from listview and that item will set in text1 and text2 variable of PageActivity class respectively.
Question: How can I return result from tab activity to my PageActivity when user select any item from list view of any Tab.
You can get the position from the ListView in the tabs, use that position to get corresponding data in the onClickListener.
Set this data in the TextViews. I am assuming ListViews' OnClickListener has reference to the TextViews
I have a custom TabHost that adds tabs like this
private void setTab(View view, String tag, Intent intent)
{
View tabView = LayoutInflater.from(context).inflate(R.layout.tabs_bg, null);
TextView tv = (TextView) view.findViewById(R.id.tabsText);
tv.setText(tag);
TabSpec setContent = mTabHost.newTabSpec(tag).setIndicator(tabView)
.setContent(intent);
mTabHost.addTab(setContent);
}
where mTabHost is the tab host and the tabs_bg.xml just has a textview in a linearlayout. (My main layout is the same as the Tab Layout example; I'm just trying to have small, text only tabs.) My info tab is invoked like this:
intent = new Intent().setClass(this, AboutScreen.class);
setTab(new TextView(this), "about", intent);
AboutScreen extends Activity, and all it does is setContentView to this
<?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">
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:id="#+id/AboutUsTitle"
android:textColor="#ffffffff" android:text="#string/about_title"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:layout_gravity="center" android:gravity="center"
android:background="#drawable/about_title"/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="15dip">
<TextView android:id="#+id/AboutContents"
android:text="#string/about_contents" android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
</LinearLayout>
</LinearLayout>
where #drawable/about_title is this:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#ffffffff"
android:endColor="#ff333333"
android:angle="90"/>
</shape>
That drawable isn't being displayed inside the FrameLayout. Everything else shows up correctly. Any ideas what I'm doing wrong?
EDIT: if I set it programmatically
TextView tvAboutUsTitle = (TextView) findViewById(R.id.AboutUsTitle);
tvAboutUsTitle.setBackgroundResource(R.drawable.about_title);
it shows up. Why is that different than setting it in the xml?
i can't see you using tv (TextView) anywhere, unless its just missing from that snippet of code?
Here is an example of how i setup 3 tabs in an activity which might help you
EDIT: I forgot to mention. In this code i also needed what i think you want, a custom tab of a single line.
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this.getApplicationContext();
application = ((rbApplication)getApplicationContext());
setContentView(R.layout.channellist);
new DownloadTask().execute();
setupTabs();
}
public void setupTabs() {
TabHost tabHost = getTabHost(); // The activity TabHost
tabHost.getTabWidget().setDividerDrawable(R.drawable.tab_divider);
TabHost.TabSpec spec; // Reusable TabSpec for each tab
Intent intent; // Reusable Intent for each tab
// Initialize a TabSpec for each tab and add it to the TabHost
intent = new Intent().setClass(application, ChannelListSubscribed.class);
spec = tabHost.newTabSpec("subscribed");
View customTabView1 = createTabView(application, "Subscribed");
spec.setIndicator(customTabView1);
spec.setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(application, ChannelListNonSubscribed.class);
spec = tabHost.newTabSpec("nonsubscribed");
View customTabView2 = createTabView(application, "Find More");
spec.setIndicator(customTabView2);
spec.setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(application,ChannelListFeatured.class);
spec = tabHost.newTabSpec("featured");
View customTabView3 = createTabView(application, "Featured");
spec.setIndicator(customTabView3);
spec.setContent(intent);
tabHost.addTab(spec);
tabHost.setCurrentTab(0);
}
private static View createTabView(final Context context, final String tabLabel) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_item, null);
TextView tv = (TextView) view.findViewById(R.id.tab_label);
tv.setText(tabLabel);
return view;
}
tab_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="10dip"
android:gravity="center"
android:orientation="vertical"
android:background="#drawable/tab_bg_selector">
<TextView
android:id="#+id/tab_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dp"
android:textColor="#drawable/tab_text_selector"/>
</LinearLayout>
I've had problems where a view is not displayed large enough due to it size seemingly being determined before it's contents are known, even though it's all held in xml (with references out to strings)
Have you tried setting the layout_height and widths to numerical values (or even 'fill parent' to see if that is the case?
Also, I would simplify the layout to remove the nested LinearLayouts? as they appear unnecessary due to each only holding one TextView
Since we're not using the tab view now anyway, I'm going to close this, since this
TextView tvAboutUsTitle = (TextView) findViewById(R.id.AboutUsTitle);
tvAboutUsTitle.setBackgroundResource(R.drawable.about_title);
fixed the problem I was having anyway, even if I don't really know why.
I am building a tabbed application. Things work wonderfully with TabHost. Unfortunately, my team lead does not like the look of the tabs. He doesn't like the tiny icon and the gaps between the tabs. So, I either need to modify TabHost or use an ActivityGroup.
My first attempt was at changing TabHost.
Here is the drawable for one of my tabs:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- When selected, use grey -->
<item android:drawable="#drawable/ic_tab_timeline_grey"
android:state_selected="true" />
<!-- When not selected, use white-->
<item android:drawable="#drawable/ic_tab_timeline_white" />
<!-- This is a state-list drawable, which you will apply as the tab image. When the tab state changes, the tab icon will automatically switch between the images defined here. -->
</selector>
I initialize the tab in my main activity:
// Initialize a TabSpec for each tab and add it to the TabHost
intent = new Intent().setClass(this, TimelineActivity.class);
spec = tabHost.newTabSpec("timeline") .setIndicator("",
res.getDrawable(R.drawable.ic_tab_timeline))
.setContent(intent);
tabHost.addTab(spec);
(Note that I set the Indicator to blanks.)
Then, I set the background image:
TabWidget tw = getTabWidget();
//changeTabWidgetStyle(tw);
View tempView = tabHost.getTabWidget().getChildAt(0);
tempView.setBackgroundDrawable(getResources().getDrawable(R.drawable.timeline_on));
This successfully sets the background to my desired image. However, my tab still has the tiny icon, which overlays my background image. How can I get rid of the icon? I tried setting the Drawable to null when I initialize the tab, but this causes my app to crash.
Even if I can get this to work, it looks like I will still have spaces between the tabs. How can I get rid of those?
If this doesn't work, I may have to go with an ActivityGroup. I would rather not, though, because that seems more complicated.
I'm using this example: android: using ActivityGroup to embed activities
LocalActivityManager mgr = getLocalActivityManager();
Intent i = new Intent(this, SomeActivity.class);
Window w = mgr.startActivity("unique_per_activity_string", i);
View wd = w != null ? w.getDecorView() : null;
if(wd != null) {
mSomeContainer.addView(wd);
}
I can get the "tabs" to change and inflate layouts, but I can't add the local activity. I'm not sure what sort of "container" to add the view to. What should my xml layout look like?
Here is the method i used to successfully successfully create completely custom looking tabs on a recent project.
The idea is to use a hidden TabWidget in your layout and control it with a customized LinearLayout containing Buttons. This way, you can more easily customize the buttons to look however you'd like. You'll control the actual TabWidget in your Activity within each button's OnClick.
Create your layout with both the TabWidget and the Buttons:
<?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:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:gravity="bottom">
<TabWidget android:id="#android:id/tabs"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:visibility="gone" />
<LinearLayout android:id="#+id/tabbar"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android:id="#+id/firstButton"
android:layout_alignParentTop="true" android:background="#drawable/btn_first_on"
android:layout_width="100dp" android:layout_height="43dp"
android:clickable="true"></Button>
<Button android:id="#+id/secondButton"
android:layout_alignParentTop="true" android:background="#drawable/btn_second_off"
android:layout_height="43dp" android:layout_width="100dp"
android:clickable="true"></Button>
<Button android:id="#+id/thirdButton"
android:layout_alignParentTop="true" android:background="#drawable/btn_third_off"
android:layout_height="43dp" android:layout_width="100dp"
android:clickable="true"></Button>
<Button android:id="#+id/forthButton"
android:layout_alignParentTop="true" android:background="#drawable/btn_forth_off"
android:layout_height="43dp" android:layout_width="100dp"
android:clickable="true"></Button>
</LinearLayout>
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_below="#+id/tabbar" />
</RelativeLayout>
</TabHost>
Set up the onCreate of your activity to handle using the buttons for adjusting the tab views:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// tabs
firstButton = (Button) findViewById(R.id.firstButton);
secondButton = (Button) findViewById(R.id.secondButton);
thirdButton = (Button) findViewById(R.id.thirdButton);
forthButton = (Button) findViewById(R.id.forthButton);
Resources res = getResources(); // Resource object to get Drawables
final TabHost tabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Resusable TabSpec for each tab
Intent intent; // Reusable Intent for each tab
intent = new Intent().setClass(this, FirstGroupActivity.class);
spec = tabHost.newTabSpec("first").setIndicator("First").setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, SecondGroupActivity.class);
spec = tabHost.newTabSpec("second").setIndicator("Second").setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, ThirdGroupActivity.class);
spec = tabHost.newTabSpec("third").setIndicator("Third").setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, ForthActivity.class);
spec = tabHost.newTabSpec("forth").setIndicator("Forth").setContent(intent);
tabHost.addTab(spec);
tabHost.setCurrentTab(0);
firstButton.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
tabHost.setCurrentTab(0);
firstButton.setBackgroundResource(R.drawable.btn_first_on);
secondButton.setBackgroundResource(R.drawable.btn_second_off);
thirdButton.setBackgroundResource(R.drawable.btn_third_off);
forthButton.setBackgroundResource(R.drawable.btn_forth_off);
}
});
secondButton.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
tabHost.setCurrentTab(1);
firstButton.setBackgroundResource(R.drawable.btn_first_off);
secondButton.setBackgroundResource(R.drawable.btn_second_on);
thirdButton.setBackgroundResource(R.drawable.btn_third_off);
forthButton.setBackgroundResource(R.drawable.btn_forth_off);
}
});
thirdButton.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
tabHost.setCurrentTab(3);
firstButton.setBackgroundResource(R.drawable.btn_first_off);
secondButton.setBackgroundResource(R.drawable.btn_second_off);
thirdButton.setBackgroundResource(R.drawable.btn_third_on);
forthButton.setBackgroundResource(R.drawable.btn_forth_off);
}
});
forthButton.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
tabHost.setCurrentTab(4);
firstButton.setBackgroundResource(R.drawable.btn_first_off);
secondButton.setBackgroundResource(R.drawable.btn_second_off);
thirdButton.setBackgroundResource(R.drawable.btn_third_off);
forthButton.setBackgroundResource(R.drawable.btn_forth_on);
}
});
}
As you can see, I'm using drawables for the images of the buttons on and off. Using this technique, you're not limited to the options available when simply just trying to customize the look of the TabWidget's tabs and you can create a completely custom look to your tabs.
Also, as a rule of thumb, it's a bad idea to use an ActivityGroup in android tabs. That approach eats up a lot of system resources. A better approach and one that I've also implemented on this project is to keep track of the views through an array of views and then swap them out as needed.
Further to SBerg413's answer you can set the button images for your new tab buttons to transparent images. Then add an ImageView to display under the buttons (use RelativeLayout to get the ImageView to appear in the same space as the buttons) and simply switch the image displayed there depending on which button is pressed.
This way you can have tab buttons of different shapes and generally more freedom of design for the tab bar and use the buttons as a basic hit box for each tab button.
I have an android activity in which I'm using tabs.
public class UnitActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.unit_view);
TabHost tabHost = getTabHost();
TabSpec spec;
spec = tabHost.newTabSpec("controls");
spec.setIndicator("Control");
spec.setContent(R.layout.unit_control);
tabHost.addTab(spec);
spec = tabHost.newTabSpec("data");
spec.setIndicator("Data");
spec.setContent(R.layout.unit_data);
tabHost.addTab(spec);
}
}
However when I run the program it crashes with the error:
"Could not create tab content because could not find view with id 2130903042". I don't understand what the problem is because R.layout.unit_data refers to a layout file in my resource directory (res/layout/unit_data.xml)
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout
android:stretchColumns="*"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Spinner android:id="#+id/unit_num"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="#string/choose_unit"/>
<TableRow android:padding="2dp">
<TextView
android:gravity="right"
android:padding="5dp"
android:text="#string/Power"/>
<TextView android:id="#+id/unit_power"
android:layout_span="3"
android:gravity="center"
android:padding="5dp"
android:background="#android:color/white"
android:textColor="#android:color/black"
android:text="AUTO"/>
</TableRow>
...
</TableLayout>
</ScrollView>
as far as I can tell unit_data.xml is well formed and I've even referenced it successfully in another activity
class UnitData extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.unit_data);
Toast.makeText(this, "Hi from UnitData.onCreate", 5);
}
}
which does not give an error and renders the layout just fine.
What's going on? Why can't I reference this layout when creating a tab?
While Activity.setContentView takes an id of a Layout, TabSpec.setContent takes an id of a View. This means you need to pass an id that looks like R.id.something and not R.layout.something.
To solve your particular problem, give the top level view in your layout a view id:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/unit_data"> <!-- NOTE THE CHANGE -->
...
</ScrollView>
and update your source:
public class UnitActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.unit_view);
TabHost tabHost = getTabHost();
TabSpec spec;
spec = tabHost.newTabSpec("controls");
spec.setIndicator("Control");
spec.setContent(R.id.unit_control); // NOTE THE CHANGE
tabHost.addTab(spec);
spec = tabHost.newTabSpec("data");
spec.setIndicator("Data");
spec.setContent(R.id.unit_data); // NOTE THE CHANGE
tabHost.addTab(spec);
}
}
For more information, see the tab examples in the ApiDemos:
If you have your tab layout in a different file, you have to inflate the XML.
spec = tabHost.newTabSpec("data");
spec.setIndicator("Data");
// Add the layout to your tab view
getLayoutInflater().inflate(R.layout.unit_data, tabHost.getTabContentView(), true);
spec.setContent(R.id.unit_data);
tabHost.addTab(spec);
You also have to use LayoutInflater after TabHost
LayoutInflater.from(this).inflate(R.layout.unit_data, tabHost.getTabContentView(), true);
I also got stuck with this and finally figure it out.