Android how to interact with Fragment tabs

CQM picture CQM · Nov 9, 2011 · Viewed 10.6k times · Source

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.

Answer

Zsombor Erdődy-Nagy picture Zsombor Erdődy-Nagy · Nov 9, 2011

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.