Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.example.android.supportv4.app;
     17 
     18 //BEGIN_INCLUDE(complete)
     19 import java.util.HashMap;
     20 
     21 import com.example.android.supportv4.R;
     22 
     23 import android.content.Context;
     24 import android.os.Bundle;
     25 import android.support.v4.app.Fragment;
     26 import android.support.v4.app.FragmentActivity;
     27 import android.support.v4.app.FragmentTransaction;
     28 import android.view.View;
     29 import android.widget.TabHost;
     30 
     31 /**
     32  * This demonstrates how you can implement switching between the tabs of a
     33  * TabHost through fragments.  It uses a trick (see the code below) to allow
     34  * the tabs to switch between fragments instead of simple views.
     35  */
     36 public class FragmentTabs extends FragmentActivity {
     37     TabHost mTabHost;
     38     TabManager mTabManager;
     39 
     40     @Override
     41     protected void onCreate(Bundle savedInstanceState) {
     42         super.onCreate(savedInstanceState);
     43 
     44         setContentView(R.layout.fragment_tabs);
     45         mTabHost = (TabHost)findViewById(android.R.id.tabhost);
     46         mTabHost.setup();
     47 
     48         mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
     49 
     50         mTabManager.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
     51                 FragmentStackSupport.CountingFragment.class, null);
     52         mTabManager.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
     53                 LoaderCursorSupport.CursorLoaderListFragment.class, null);
     54         mTabManager.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
     55                 LoaderCustomSupport.AppListFragment.class, null);
     56         mTabManager.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),
     57                 LoaderThrottleSupport.ThrottledLoaderListFragment.class, null);
     58 
     59         if (savedInstanceState != null) {
     60             mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
     61         }
     62     }
     63 
     64     @Override
     65     protected void onSaveInstanceState(Bundle outState) {
     66         super.onSaveInstanceState(outState);
     67         outState.putString("tab", mTabHost.getCurrentTabTag());
     68     }
     69 
     70     /**
     71      * This is a helper class that implements a generic mechanism for
     72      * associating fragments with the tabs in a tab host.  It relies on a
     73      * trick.  Normally a tab host has a simple API for supplying a View or
     74      * Intent that each tab will show.  This is not sufficient for switching
     75      * between fragments.  So instead we make the content part of the tab host
     76      * 0dp high (it is not shown) and the TabManager supplies its own dummy
     77      * view to show as the tab content.  It listens to changes in tabs, and takes
     78      * care of switch to the correct fragment shown in a separate content area
     79      * whenever the selected tab changes.
     80      */
     81     public static class TabManager implements TabHost.OnTabChangeListener {
     82         private final FragmentActivity mActivity;
     83         private final TabHost mTabHost;
     84         private final int mContainerId;
     85         private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
     86         TabInfo mLastTab;
     87 
     88         static final class TabInfo {
     89             private final String tag;
     90             private final Class<?> clss;
     91             private final Bundle args;
     92             private Fragment fragment;
     93 
     94             TabInfo(String _tag, Class<?> _class, Bundle _args) {
     95                 tag = _tag;
     96                 clss = _class;
     97                 args = _args;
     98             }
     99         }
    100 
    101         static class DummyTabFactory implements TabHost.TabContentFactory {
    102             private final Context mContext;
    103 
    104             public DummyTabFactory(Context context) {
    105                 mContext = context;
    106             }
    107 
    108             @Override
    109             public View createTabContent(String tag) {
    110                 View v = new View(mContext);
    111                 v.setMinimumWidth(0);
    112                 v.setMinimumHeight(0);
    113                 return v;
    114             }
    115         }
    116 
    117         public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
    118             mActivity = activity;
    119             mTabHost = tabHost;
    120             mContainerId = containerId;
    121             mTabHost.setOnTabChangedListener(this);
    122         }
    123 
    124         public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
    125             tabSpec.setContent(new DummyTabFactory(mActivity));
    126             String tag = tabSpec.getTag();
    127 
    128             TabInfo info = new TabInfo(tag, clss, args);
    129 
    130             // Check to see if we already have a fragment for this tab, probably
    131             // from a previously saved state.  If so, deactivate it, because our
    132             // initial state is that a tab isn't shown.
    133             info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
    134             if (info.fragment != null && !info.fragment.isDetached()) {
    135                 FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
    136                 ft.detach(info.fragment);
    137                 ft.commit();
    138             }
    139 
    140             mTabs.put(tag, info);
    141             mTabHost.addTab(tabSpec);
    142         }
    143 
    144         @Override
    145         public void onTabChanged(String tabId) {
    146             TabInfo newTab = mTabs.get(tabId);
    147             if (mLastTab != newTab) {
    148                 FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
    149                 if (mLastTab != null) {
    150                     if (mLastTab.fragment != null) {
    151                         ft.detach(mLastTab.fragment);
    152                     }
    153                 }
    154                 if (newTab != null) {
    155                     if (newTab.fragment == null) {
    156                         newTab.fragment = Fragment.instantiate(mActivity,
    157                                 newTab.clss.getName(), newTab.args);
    158                         ft.add(mContainerId, newTab.fragment, newTab.tag);
    159                     } else {
    160                         ft.attach(newTab.fragment);
    161                     }
    162                 }
    163 
    164                 mLastTab = newTab;
    165                 ft.commit();
    166                 mActivity.getSupportFragmentManager().executePendingTransactions();
    167             }
    168         }
    169     }
    170 }
    171 //END_INCLUDE(complete)
    172