I have the problem that the tab content does not change when I use tabHost.setCurrentTab(...). One can see, that the corresponding tab is marked as active, the content stays the same. When I click on the tab, the content changes.
To the Setup.
I have different functionalities in one app using fragments. One fragment contains a tabhost. Each tab has its own layout and the fragment should switch between those tabs and show a selection of tabs depending on the state of the app.
I'll try to quote the important code passages.
The main xml file of the fragment:
<TabHost
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/tabHost"
xmlns:android="http://schemas.android.com/apk/res/android">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="fill"
android:background="#color/colorPrimary"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<include layout="#layout/fragment_master_emg_start"
android:layout_height="445dp"
android:layout_width="fill_parent"
android:layout_gravity="center|bottom"/>
<include layout="#layout/fragment_master_emg_setup"
android:layout_height="445dp"
android:layout_width="fill_parent"
android:layout_gravity="center|bottom"/>
... some more includes
</FrameLayout>
</TabHost>
The xml files included just contain a relative layout and a bunch of buttons and textviews.
The Fragments onCreate Method:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Get View
View rootView = inflater.inflate(R.layout.fragment_master_emg, container, false);
Button button= (Button)rootView.findViewById(R.id.button);
button.setText("test");
TabHost tabHost=(TabHost)rootView.findViewById(R.id.tabHost);
tabHost.setup();
// Tabs
// Setup - Start Tab
TabHost.TabSpec t=tabHost.newTabSpec("Tab0");
t.setContent(R.id.master_emg_start);
t.setIndicator("EMG Measurement - Setup");
tabHost.addTab(t);
TabHost.TabSpec t0=tabHost.newTabSpec("Tab1");
t0.setContent(R.id.master_emg_setup);
t0.setIndicator("Setup");
tabHost.addTab(t0);
.... more tabs
....
// Set initial visibility
tabHost.getTabWidget().getChildAt(0).setVisibility(View.VISIBLE);
tabHost.getTabWidget().getChildAt(1).setVisibility(View.GONE);
// Buttons to switch tabs
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TabHost tabHost=(TabHost)getActivity().findViewById(R.id.tabHost);
tabHost.getTabWidget().getChildAt(0).setVisibility(View.GONE);
tabHost.getTabWidget().getChildAt(1).setVisibility(View.VISIBLE);
tabHost.getTabWidget().setCurrentTab(1);
}
});
I've just included two tabs in this excerpt, but this would be the basic procedure.
I've tried to invalidade the tab host in order to have everythin redrawn. This did not change anything.
For anyone landing here for this problem solution:
Use :
tabHost.setCurrentTab(tabNumber);
Instead of :
tabHost.getTabWidget().setCurrentTab(tabNumber);
Related
I have a project I am working on in Android. I have one big fragment that covers the whole of the screen in my main activity. Normally I for each ui screen the user uses I would just do a replace command and swap the fragments for each screen.
In my current one I want to put a tablayout/viewpager combo with three different fragments and depending on what tab is pushed I will show a new fragment. Problem with this is that is a tablayout showing three different fragments inside another fragment. Is this even possible or recommended? and if I have to change it to a new activity. Would the navigation drawer act normally and just shut as I loaded the activity or is there going to be a problem there as well.
Thanks for your help
You can check below official documentation for the same or can use my demo snippet:
https://developer.android.com/reference/android/support/v4/app/FragmentTabHost.html
Try to do this to handle the Tabs in main fragment:
public class MainFragment extends Fragment {
private FragmentTabHost mTabHost;
//Mandatory Constructor
public MainFragment() {
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tabs,container, false);
mTabHost = (FragmentTabHost)rootView.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("fragmentb").setIndicator("Fragment B"),
FragmentB.class, null);
mTabHost.addTab(mTabHost.newTabSpec("fragmentc").setIndicator("Fragment C"),
FragmentC.class, null);
mTabHost.addTab(mTabHost.newTabSpec("fragmentd").setIndicator("Fragment D"),
FragmentD.class, null);
return rootView;
}
}
With this tabs layout:
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
Yes, TabLayout with viewPager will maintain it's different fragments in the memory.
Since, there are going to be only 3 tabs in your case it won't affect your memory performance, you can go with pagerAdapter.
You can reuse a single fragment for other tabs, but as i said since there are only 3 tabs, it won't affect your performance.
And Yes you can have tabLayout inside your main fragment, you main fragment is a part of your activity right, it will follow the same life cycle as the hosting activity except few other callbacks.
I have great problems getting the Navigation Tabs work. I am aware of this guide http://developer.android.com/guide/topics/ui/actionbar.html#Tabs
but I have problems understanding the article. It says the following:
To get started, your layout must include a ViewGroup in which you place each Fragment associated with a tab. Be sure the ViewGroup has a resource ID so you can reference it from your code and swap the tabs within it. Alternatively, if the tab content will fill the activity layout, then your activity doesn't need a layout at all (you don't even need to call setContentView()). Instead, you can place each fragment in the default root view, which you can refer to with the android.R.id.content ID.
As I don't use a Fragment for my Main Layout, but for others, I think the "alternative" way is right for me (I would like Tab 1 to be the Main Layout I have right now and then 2 and 3 to be my fragments), but I don't know how to accomplish this. Can someone maybe help out on this?
I was able to set up the tabs and the TabListener, so that is not the problem. The problem is that the first tab is NOT supposed to be a fragment, but my main activity layout! This is where I need help!
I did try to use my main activity-layout for a fragment, but for some reason if I click that tab, the tab changes but the screen stays white. I cannot see my fragment view.
The old code was:
mListView = (ListView) findViewById(R.id.list_view);
mListView.setAdapter(mAdapter);
mListView.setTextFilterEnabled(true);
and I've changed it in the fragment to:
View view = inflater.inflate(R.layout.list, container, false);
mListView = (ListView) view.findViewById(R.id.list_view);
mListView.setAdapter(mAdapter);
mListView.setTextFilterEnabled(true);
// do stuff here //
return view;
and this is list.xml:
<FrameLayout xmlns:android:="http://schemas.android.com/apk/res/android"
android:id="#id/main_fragment"
android:layout_width="match_parent"
android:layout:height=match_parent">
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout:height=0dp"
android:layout_weight="1"
android:layout:marginTop="20dp"
android:descendantFocusability="blocksDescendants"/>
</FrameLayout>
how come I cannot see anything?
Solved: This was because I set the height to 0dp.
Please update your code by this:
<FrameLayout xmlns:android:="http://schemas.android.com/apk/res/android"
android:id="#+id/main_fragment"
android:layout_width="match_parent"
android:layout:height=match_parent">
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:descendantFocusability="blocksDescendants"/>
</FrameLayout>
I'am build an app with an ActionBar and two Tabs below.
Everything works fine if the device / emulator isnt rotated. If rotated, tab state switches automaticale to tab1 (normal, because onCreate get called) but the content dont get changed. If I select a tab in the new orientation, the onCreateView() method from the selected Fragment get called but the view dont get updated (stay always the same). Any Tips?
The code.
Main Activity:
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab ATab = actionbar.newTab().setText(R.string.player);
ActionBar.Tab BTab = actionbar.newTab().setText(R.string.stations);
Fragment AFragment = new AFragment();
Fragment BFragment = new BFragment();
PlayerTab.setTabListener(new MyTabsListener(AFragment));
StationsTab.setTabListener(new MyTabsListener(BFragment));
actionbar.addTab(ATab);
actionbar.addTab(BTab);
With identical tabs that display a simple textview. The textview simple say which tab is selected.
Fragments:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.a, container, false);
}
The Fragment layout, mentioned above, only contains a TextView with hardcoded Text. (Only for testing purposes)
The Main layout looks like 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:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
</LinearLayout>
Solved. I have recreated the fragment everytime, doesnt do that anymore solved it.
Changed in my TabListener and onTabSelected(Tab tab, FragmentTransaction ft), ft.add() to ft.replace()
I am using actionbarsherlock library to have action-bar in my application,
I am also using view-pager to switch between the page,
Now the problem is i want only one tab with two fragment to display data regarding each other.
What could be the possible way to do this?
I have been going through like the one below but unsuccessful
In main fragment i am inflating a xml like this
<code>
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragView = inflater.inflate(R.layout.album_view_main, container, false);
return fragView;
}
</code>
xml fie is look like this
<code>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/fragment_album_view"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="3"
class="com.nix.music.activity.fragments.AlbumFragMent" />
<FrameLayout
android:id="#+id/frame_list_song"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="2" >
</FrameLayout>
</LinearLayout>
</code>
but the problem is i cannot find "frame_list_song" in AlbumFragment class it appears null
what could be the way around ?
thank you
This layout should be set in the parent activity using setContentView(). Then, you would be able to do something like getActivity().findViewById(R.id.frame_list_song) from your AlbumFragment. The better way would be to use an interface and transfer control to the main activity, and not access other fragments directly.
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)