Android how to interact with Fragment tabs
You can't put Activities into Fragments, it's jut that simple. You have to convert your Activities that serve the tab-contents into Fragments. It shouldn't be a problem, given that you don't use fragments in those Activities.
So here are 2 rules to follow:
- You can't put Activities into Fragments.
- You can't put Fragments into Fragments.
I recommend that you keep that bottom fragment on your layout around just to handle the tab-switches in the tab-widget. If a tab switch happens, you report this to the parent Activity, which will load the corresponding Fragment into the are above the tab-fragment. For this to work, you'd have to modify you layout so it has a ViewGroup above the tab-fragment and below the header. You'd dynamically load the fragments with the tab-contents into that ViewGroup.
Here's the layout (maintabholder.xml):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/header" android:layout_alignParentTop="true" android:id="@+id/headerArea"></include>
<FrameLayout android:id="@+id/TabContent"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
<fragment
class="my.package.name.MainNav"
android:id="@+id/fragment_tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
When a tab-switch happens in your bottom fragment, you tell this to the parent Activity:
...
(YourActivity)getActivity().switchToTab(tabId);
...
And in the YourActivity:
...
public void switchToTab(int tabId){
switch(tabId){
...
case 2:
getSupportFragmentManager().beginTransaction().replace(R.id.TabContent, TabContentFragment2.newInstance(), "someTag").commit().
break;
...
}
}
Something like that.
CQM
Updated on June 05, 2022Comments
-
CQM almost 2 years
Hello I am having difficulty changing the visual view of the fragment activity. I created all the tabs but onClick I do not know how to pass the activity into that white space.
so the structure of this is a simple activity named
Main
which just sets the content view to amaintabholder.xml
document that holds the fragment view which connects to a class namedMainNav
whose content view contains all the tabs at the bottom.maintabholder.xml
:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <include layout="@layout/header" android:layout_alignParentTop="true" android:id="@+id/headerArea"></include> <fragment class="my.package.name.MainNav" android:id="@+id/fragment_tabs" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
MainNav.java code snippet
:@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { mRoot = inflater.inflate(R.layout.fragment_tabs, null); mTabHost = (TabHost) mRoot.findViewById(android.R.id.tabhost); setupTabs(); return mRoot; }
and R.layout.fragment_tabs:
<?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" android:background="#EFEFEF"> <RelativeLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TabWidget android:id="@android:id/tabs" android:layout_alignParentBottom="true" android:layout_width="fill_parent" android:background="@drawable/tab_background" android:gravity="center_horizontal" android:layout_height="wrap_content" > </TabWidget> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="wrap_content"> <FrameLayout android:id="@+id/tab_1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <FrameLayout android:id="@+id/tab_2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <FrameLayout android:id="@+id/tab_3" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <FrameLayout android:id="@+id/tab_4" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <FrameLayout android:id="@+id/tab_5" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </FrameLayout> </RelativeLayout>
and Finally the contents of an Activity that I want to load into the Fragment (upon pressing the tab1 button)
public class HomeFragment extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.home); } }
That is to help you get the gist of things, but the problem occurs here in MainNav.java:
@Override public void onTabChanged(String tabId) { Log.d(TAG, "onTabChanged(): tabId=" + tabId); if (TAB_HOME.equals(tabId)) { updateTab(tabId, R.id.tab_1); mCurrentTab = 0; return; } }
when a tab is clicked, it is registered in the
onTabChanged
activity, and theupdateTab
function is called:private void updateTab(String tabId, int placeholder) { FragmentManager fm = getFragmentManager(); if (fm.findFragmentByTag(tabId) == null) { //fm.beginTransaction() // .replace(placeholder, /*need fragment object here*/ , tabId) // .commit(); // } }
the commented out
replace
method is looking for an(int, fragment, string)
and I guess it should then change the white space for me.but I don't understand where I get the fragment object from! This phantom object needs to somehow contain my
HomeFragment
's xml layout and allow me to interact with everything else I've coded for theHomeFragment
activity.My first hunch is that my
HomeFragment
activity needs toextend FragmentActivity
instead just activity. But this is where I am hitting a wall.There is very little documentation on the compatibility pack methods, but the documentation for TabActivity says not to use TabActivity anymore, so here I am. Developing for Android 2.2+
Insight appreciated.
-
CQM over 12 yearsthat was very helpful! one thing I have is that one of my activities contains a google map. So it has to extend MapActivity . If I change that activity to FragmentActivity then it crashes with the obvious error "mapview can only be called from MapActivity" , this is a problem for me and this fragment structure unless I created some kind of hybrid MapFragmentActivity.....
-
Zsombor Erdődy-Nagy over 12 yearsConsider using this lib github.com/petedoyle/android-support-v4-googlemaps . I don't have any experience with it though, but it might work.
-
SandWyrm over 11 years@ZsomborErdődy-Nagy - you recommend the support library but then also state that fragments can't be inside fragments, this is no longer true. The support library used to have some issues with this, but since v11, released sometime around your posting, there is provisioning for nested fragments with some slightly specific logic to support it (getChildFragmentManager). So for anyone else that finds this thread, Activities may not be in fragments, but fragments may now be in fragments.