Android how to interact with Fragment tabs

10,626

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:

  1. You can't put Activities into Fragments.
  2. 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.

Share:
10,626
CQM
Author by

CQM

Updated on June 05, 2022

Comments

  • CQM
    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 a maintabholder.xml document that holds the fragment view which connects to a class named MainNav 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 the updateTab 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 the HomeFragment activity.

    My first hunch is that my HomeFragment activity needs to extend 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
    CQM over 12 years
    that 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
    Zsombor Erdődy-Nagy over 12 years
    Consider using this lib github.com/petedoyle/android-support-v4-googlemaps . I don't have any experience with it though, but it might work.
  • SandWyrm
    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.