Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2012 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.apis.app;
     17 
     18 import java.util.ArrayList;
     19 
     20 import com.example.android.apis.R;
     21 
     22 import android.app.Fragment;
     23 import android.app.FragmentManager;
     24 import android.app.FragmentTransaction;
     25 import android.content.Context;
     26 import android.os.Bundle;
     27 import android.view.LayoutInflater;
     28 import android.view.View;
     29 import android.view.ViewGroup;
     30 import android.widget.TabHost;
     31 
     32 /**
     33  * Sample fragment that contains tabs of other fragments.
     34  */
     35 public class FragmentTabsFragment extends Fragment {
     36     TabManager mTabManager;
     37 
     38     @Override
     39     public void onCreate(Bundle savedInstanceState) {
     40         super.onCreate(savedInstanceState);
     41         mTabManager = new TabManager(getActivity(), getChildFragmentManager(),
     42                 R.id.realtabcontent);
     43     }
     44 
     45     @Override
     46     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     47             Bundle savedInstanceState) {
     48         View v = inflater.inflate(R.layout.fragment_tabs_fragment, container, false);
     49         TabHost host = mTabManager.handleCreateView(v);
     50 
     51         mTabManager.addTab(host.newTabSpec("result").setIndicator("Result"),
     52                 FragmentReceiveResult.ReceiveResultFragment.class, null);
     53         mTabManager.addTab(host.newTabSpec("contacts").setIndicator("Contacts"),
     54                 LoaderCursor.CursorLoaderListFragment.class, null);
     55         mTabManager.addTab(host.newTabSpec("apps").setIndicator("Apps"),
     56                 LoaderCustom.AppListFragment.class, null);
     57         mTabManager.addTab(host.newTabSpec("throttle").setIndicator("Throttle"),
     58                 LoaderThrottle.ThrottledLoaderListFragment.class, null);
     59 
     60         return v;
     61     }
     62 
     63     @Override
     64     public void onViewStateRestored(Bundle savedInstanceState) {
     65         super.onViewStateRestored(savedInstanceState);
     66         mTabManager.handleViewStateRestored(savedInstanceState);
     67     }
     68 
     69     @Override
     70     public void onDestroyView() {
     71         super.onDestroyView();
     72         mTabManager.handleDestroyView();
     73     }
     74 
     75     @Override
     76     public void onSaveInstanceState(Bundle outState) {
     77         super.onSaveInstanceState(outState);
     78         mTabManager.handleSaveInstanceState(outState);
     79     }
     80 
     81     /**
     82      * This is a helper class that implements a generic mechanism for
     83      * associating fragments with the tabs in a tab host.  DO NOT USE THIS.
     84      * If you want tabs in a fragment, use the support v13 library's
     85      * FragmentTabHost class, which takes care of all of this for you (in
     86      * a simpler way even).
     87      */
     88     public static class TabManager implements TabHost.OnTabChangeListener {
     89         private final Context mContext;
     90         private final FragmentManager mManager;
     91         private final int mContainerId;
     92         private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
     93         private TabHost mTabHost;
     94         private TabInfo mLastTab;
     95         private boolean mInitialized;
     96         private String mCurrentTabTag;
     97 
     98         static final class TabInfo {
     99             private final String tag;
    100             private final Class<?> clss;
    101             private final Bundle args;
    102             private Fragment fragment;
    103 
    104             TabInfo(String _tag, Class<?> _class, Bundle _args) {
    105                 tag = _tag;
    106                 clss = _class;
    107                 args = _args;
    108             }
    109         }
    110 
    111         static class DummyTabFactory implements TabHost.TabContentFactory {
    112             private final Context mContext;
    113 
    114             public DummyTabFactory(Context context) {
    115                 mContext = context;
    116             }
    117 
    118             @Override
    119             public View createTabContent(String tag) {
    120                 View v = new View(mContext);
    121                 v.setMinimumWidth(0);
    122                 v.setMinimumHeight(0);
    123                 return v;
    124             }
    125         }
    126 
    127         public TabManager(Context context, FragmentManager manager, int containerId) {
    128             mContext = context;
    129             mManager = manager;
    130             mContainerId = containerId;
    131         }
    132 
    133         public TabHost handleCreateView(View root) {
    134             if (mTabHost != null) {
    135                 throw new IllegalStateException("TabHost already set");
    136             }
    137             mTabHost = (TabHost)root.findViewById(android.R.id.tabhost);
    138             mTabHost.setup();
    139             mTabHost.setOnTabChangedListener(this);
    140             return mTabHost;
    141         }
    142 
    143         public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
    144             tabSpec.setContent(new DummyTabFactory(mContext));
    145             String tag = tabSpec.getTag();
    146             TabInfo info = new TabInfo(tag, clss, args);
    147             mTabs.add(info);
    148             mTabHost.addTab(tabSpec);
    149         }
    150 
    151         public void handleViewStateRestored(Bundle savedInstanceState) {
    152             if (savedInstanceState != null) {
    153                 mCurrentTabTag = savedInstanceState.getString("tab");
    154             }
    155             mTabHost.setCurrentTabByTag(mCurrentTabTag);
    156 
    157             String currentTab = mTabHost.getCurrentTabTag();
    158 
    159             // Go through all tabs and make sure their fragments match
    160             // the correct state.
    161             FragmentTransaction ft = null;
    162             for (int i=0; i<mTabs.size(); i++) {
    163                 TabInfo tab = mTabs.get(i);
    164                 tab.fragment = mManager.findFragmentByTag(tab.tag);
    165                 if (tab.fragment != null && !tab.fragment.isDetached()) {
    166                     if (tab.tag.equals(currentTab)) {
    167                         // The fragment for this tab is already there and
    168                         // active, and it is what we really want to have
    169                         // as the current tab.  Nothing to do.
    170                         mLastTab = tab;
    171                     } else {
    172                         // This fragment was restored in the active state,
    173                         // but is not the current tab.  Deactivate it.
    174                         if (ft == null) {
    175                             ft = mManager.beginTransaction();
    176                         }
    177                         ft.detach(tab.fragment);
    178                     }
    179                 }
    180             }
    181 
    182             // We are now ready to go.  Make sure we are switched to the
    183             // correct tab.
    184             mInitialized = true;
    185             ft = doTabChanged(currentTab, ft);
    186             if (ft != null) {
    187                 ft.commit();
    188                 mManager.executePendingTransactions();
    189             }
    190         }
    191 
    192         public void handleDestroyView() {
    193             mCurrentTabTag = mTabHost.getCurrentTabTag();
    194             mTabHost = null;
    195             mTabs.clear();
    196             mInitialized = false;
    197         }
    198 
    199         public void handleSaveInstanceState(Bundle outState) {
    200             outState.putString("tab", mTabHost != null
    201                     ? mTabHost.getCurrentTabTag() : mCurrentTabTag);
    202         }
    203 
    204         @Override
    205         public void onTabChanged(String tabId) {
    206             if (!mInitialized) {
    207                 return;
    208             }
    209             FragmentTransaction ft = doTabChanged(tabId, null);
    210             if (ft != null) {
    211                 ft.commit();
    212             }
    213         }
    214 
    215         private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {
    216             TabInfo newTab = null;
    217             for (int i=0; i<mTabs.size(); i++) {
    218                 TabInfo tab = mTabs.get(i);
    219                 if (tab.tag.equals(tabId)) {
    220                     newTab = tab;
    221                 }
    222             }
    223             if (newTab == null) {
    224                 throw new IllegalStateException("No tab known for tag " + tabId);
    225             }
    226             if (mLastTab != newTab) {
    227                 if (ft == null) {
    228                     ft = mManager.beginTransaction();
    229                 }
    230                 if (mLastTab != null) {
    231                     if (mLastTab.fragment != null) {
    232                         ft.detach(mLastTab.fragment);
    233                     }
    234                 }
    235                 if (newTab != null) {
    236                     if (newTab.fragment == null) {
    237                         newTab.fragment = Fragment.instantiate(mContext,
    238                                 newTab.clss.getName(), newTab.args);
    239                         ft.add(mContainerId, newTab.fragment, newTab.tag);
    240                     } else {
    241                         ft.attach(newTab.fragment);
    242                     }
    243                 }
    244 
    245                 mLastTab = newTab;
    246             }
    247             return ft;
    248         }
    249     }
    250 }
    251 //END_INCLUDE(complete)
    252