FragmentTabHost.java revision 74c671b3b67000bf16b4865a8d361344310dccbe
127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich/* 227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * Copyright (C) 2012 The Android Open Source Project 327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * 427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * Licensed under the Apache License, Version 2.0 (the "License"); 524ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * you may not use this file except in compliance with the License. 624ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * You may obtain a copy of the License at 724ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * 827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * http://www.apache.org/licenses/LICENSE-2.0 924ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * 1027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * Unless required by applicable law or agreed to in writing, software 1124ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 1224ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1324ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * See the License for the specific language governing permissions and 1424ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes * limitations under the License. 1527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich */ 1627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 1727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichpackage android.support.v4.app; 1827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 1927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport java.util.ArrayList; 2024ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes 2124ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughesimport android.content.Context; 2227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport android.content.res.TypedArray; 2327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport android.os.Bundle; 2427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport android.os.Parcel; 2527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport android.os.Parcelable; 2627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport android.util.AttributeSet; 27be509c9c7de5929d014dfe6d45e71cc8454ede0fJack Palevichimport android.view.View; 2827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevichimport android.view.ViewGroup; 29be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevichimport android.widget.FrameLayout; 30be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevichimport android.widget.LinearLayout; 31be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevichimport android.widget.TabHost; 32be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevichimport android.widget.TabWidget; 33be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich 34be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich/** 35be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich * Special TabHost that allows the use of {@link Fragment} objects for 3627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * its tab content. When placing this in a view hierarchy, after inflating 3727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * the hierarchy you must call {@link #setup(Context, FragmentManager, int)} 3827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * to complete the initialization of the tab host. 3927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * 4027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * <p>Here is a simple example of using a FragmentTabHost in an Activity: 4127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * 4227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentTabs.java 4327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * complete} 4427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * 4527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * <p>This can also be used inside of a fragment through fragment nesting: 4627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * 4727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentTabsFragmentSupport.java 4827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * complete} 4927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich */ 5024ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughespublic class FragmentTabHost extends TabHost 5127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich implements TabHost.OnTabChangeListener { 5227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); 5327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private FrameLayout mRealTabContent; 5427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private Context mContext; 5527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private FragmentManager mFragmentManager; 5627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private int mContainerId; 5727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private TabHost.OnTabChangeListener mOnTabChangeListener; 5827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private TabInfo mLastTab; 5927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private boolean mAttached; 6027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 6127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich static final class TabInfo { 6227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private final String tag; 6327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private final Class<?> clss; 6427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private final Bundle args; 6527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private Fragment fragment; 6627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 6727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich TabInfo(String _tag, Class<?> _class, Bundle _args) { 6827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich tag = _tag; 6927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich clss = _class; 7027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich args = _args; 7127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 7227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 7317045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer 7427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich static class DummyTabFactory implements TabHost.TabContentFactory { 7527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private final Context mContext; 7627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 7727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public DummyTabFactory(Context context) { 7827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mContext = context; 7927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 8027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 8127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich @Override 8227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public View createTabContent(String tag) { 8327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich View v = new View(mContext); 8427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich v.setMinimumWidth(0); 8527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich v.setMinimumHeight(0); 8627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich return v; 8727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 8827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 8927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 9024ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes static class SavedState extends BaseSavedState { 9127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich String curTab; 9227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 9317045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer SavedState(Parcelable superState) { 9427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super(superState); 9524ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes } 9617045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer 9727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private SavedState(Parcel in) { 9827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super(in); 9927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich curTab = in.readString(); 10027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 10127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 10227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich @Override 10327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public void writeToParcel(Parcel out, int flags) { 10427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super.writeToParcel(out, flags); 10527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich out.writeString(curTab); 10627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 107be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich 108be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich @Override 109be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich public String toString() { 110be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich return "FragmentTabHost.SavedState{" 111be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich + Integer.toHexString(System.identityHashCode(this)) 112be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich + " curTab=" + curTab + "}"; 113be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich } 114be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich 11524ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes public static final Parcelable.Creator<SavedState> CREATOR 11624ce5fb2cc09d0a14406e7b935f8648c5720d27eElliott Hughes = new Parcelable.Creator<SavedState>() { 117be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich public SavedState createFromParcel(Parcel in) { 118be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich return new SavedState(in); 119be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich } 120be6eac828f5af8b608c3fa6749330f1dcd6b6206Jack Palevich 12127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public SavedState[] newArray(int size) { 12227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich return new SavedState[size]; 12327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 12427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich }; 12527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 12627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 12727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public FragmentTabHost(Context context) { 12827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // Note that we call through to the version that takes an AttributeSet, 12927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // because the simple Context construct can result in a broken object! 13027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super(context, null); 13127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich initFragmentTabHost(context, null); 13227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 13327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 13427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public FragmentTabHost(Context context, AttributeSet attrs) { 13527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super(context, attrs); 1362545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer initFragmentTabHost(context, attrs); 1372545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 1382545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer 13927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private void initFragmentTabHost(Context context, AttributeSet attrs) { 14017045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer TypedArray a = context.obtainStyledAttributes(attrs, 14127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich new int[] { android.R.attr.inflatedId }, 0, 0); 14227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mContainerId = a.getResourceId(0, 0); 14327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich a.recycle(); 14427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 14517045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer super.setOnTabChangedListener(this); 146c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich 1472545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // If owner hasn't made its own view hierarchy, then as a convenience 1482545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // we will construct a standard one here. 1492545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer if (findViewById(android.R.id.tabs) == null) { 150c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich LinearLayout ll = new LinearLayout(context); 151c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich ll.setOrientation(LinearLayout.VERTICAL); 15227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich addView(ll, new FrameLayout.LayoutParams( 15337c9b49ab5eb5a676370fd7081db0967c38e97a6Thomas Tafertshofer ViewGroup.LayoutParams.FILL_PARENT, 15417045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer ViewGroup.LayoutParams.FILL_PARENT)); 15517045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer 15617045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer TabWidget tw = new TabWidget(context); 15727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich tw.setId(android.R.id.tabs); 15827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich tw.setOrientation(TabWidget.HORIZONTAL); 15927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ll.addView(tw, new LinearLayout.LayoutParams( 16027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ViewGroup.LayoutParams.FILL_PARENT, 16127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ViewGroup.LayoutParams.WRAP_CONTENT, 0)); 16227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 163c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich FrameLayout fl = new FrameLayout(context); 164c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich fl.setId(android.R.id.tabcontent); 16527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0)); 16627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 16727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mRealTabContent = fl = new FrameLayout(context); 1682545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer mRealTabContent.setId(mContainerId); 1692545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer ll.addView(fl, new LinearLayout.LayoutParams( 1702545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer LinearLayout.LayoutParams.FILL_PARENT, 0, 1)); 17127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 17227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 17327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 17427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich /** 17527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * @deprecated Don't call the original TabHost setup, you must instead 17627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich * call {@link #setup(Context, FragmentManager)} or 1772545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer * {@link #setup(Context, FragmentManager, int)}. 1782545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer */ 1792545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer @Override @Deprecated 18027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public void setup() { 18117045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer throw new IllegalStateException( 18227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich "Must call setup() that takes a Context and FragmentManager"); 18327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 18427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 18517045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer public void setup(Context context, FragmentManager manager) { 186c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich super.setup(); 1872545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer mContext = context; 1882545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer mFragmentManager = manager; 1892545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer ensureContent(); 190c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich } 191c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich 19217045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer public void setup(Context context, FragmentManager manager, int containerId) { 19317045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer super.setup(); 19417045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer mContext = context; 19517045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer mFragmentManager = manager; 19627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mContainerId = containerId; 19727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ensureContent(); 19827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mRealTabContent.setId(containerId); 19927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 20027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // We must have an ID to be able to save/restore our state. If 20127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // the owner hasn't set one at this point, we will set it ourself. 202c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich if (getId() == View.NO_ID) { 203c620a52b69a5f29563e06497e30877809f5d67a5Jack Palevich setId(android.R.id.tabhost); 20427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 20527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 20627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 2072545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer private void ensureContent() { 2082545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer if (mRealTabContent == null) { 2092545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer mRealTabContent = (FrameLayout)findViewById(mContainerId); 21027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (mRealTabContent == null) { 21127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich throw new IllegalStateException( 21227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich "No tab content FrameLayout found for id " + mContainerId); 21327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 21427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 21527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 2162545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer 2172545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer @Override 2182545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer public void setOnTabChangedListener(OnTabChangeListener l) { 21927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mOnTabChangeListener = l; 22027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 22127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 22227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { 22327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich tabSpec.setContent(new DummyTabFactory(mContext)); 2242545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer String tag = tabSpec.getTag(); 2252545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer 2262545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer TabInfo info = new TabInfo(tag, clss, args); 22727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 22827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (mAttached) { 22927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // If we are already attached to the window, then check to make 2302545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // sure this tab's fragment is inactive if it exists. This shouldn't 2312545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // normally happen. 2322545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer info.fragment = mFragmentManager.findFragmentByTag(tag); 23327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (info.fragment != null && !info.fragment.isDetached()) { 23427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich FragmentTransaction ft = mFragmentManager.beginTransaction(); 23527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft.detach(info.fragment); 23627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft.commit(); 23727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 23827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 23927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 24027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mTabs.add(info); 24127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich addTab(tabSpec); 24227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 24327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 24427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich @Override 24527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich protected void onAttachedToWindow() { 24627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super.onAttachedToWindow(); 24727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 24827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich String currentTab = getCurrentTabTag(); 24927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 2502545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // Go through all tabs and make sure their fragments match 2512545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // the correct state. 2522545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer FragmentTransaction ft = null; 25327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich for (int i=0; i<mTabs.size(); i++) { 25427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich TabInfo tab = mTabs.get(i); 25527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich tab.fragment = mFragmentManager.findFragmentByTag(tab.tag); 25627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (tab.fragment != null && !tab.fragment.isDetached()) { 25727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (tab.tag.equals(currentTab)) { 25827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // The fragment for this tab is already there and 2592545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // active, and it is what we really want to have 2602545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer // as the current tab. Nothing to do. 2612545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer mLastTab = tab; 26227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } else { 26317045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer // This fragment was restored in the active state, 26427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // but is not the current tab. Deactivate it. 26527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (ft == null) { 26627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft = mFragmentManager.beginTransaction(); 26717045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer } 26817045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer ft.detach(tab.fragment); 26917045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer } 27017045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer } 27117045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer } 27227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 27327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // We are now ready to go. Make sure we are switched to the 27427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich // correct tab. 27527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mAttached = true; 27627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft = doTabChanged(currentTab, ft); 27727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (ft != null) { 27827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft.commit(); 2792545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer mFragmentManager.executePendingTransactions(); 2802545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 2812545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 28227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 28327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich @Override 28427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich protected void onDetachedFromWindow() { 28527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super.onDetachedFromWindow(); 28627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mAttached = false; 28727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 2882545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer 2892545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer @Override 2902545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer protected Parcelable onSaveInstanceState() { 29127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich Parcelable superState = super.onSaveInstanceState(); 29227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich SavedState ss = new SavedState(superState); 29327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ss.curTab = getCurrentTabTag(); 29427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich return ss; 29527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 2962545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer 2972545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer @Override 2982545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer protected void onRestoreInstanceState(Parcelable state) { 29927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich SavedState ss = (SavedState)state; 30027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich super.onRestoreInstanceState(ss.getSuperState()); 30127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich setCurrentTabByTag(ss.curTab); 3022545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 3032545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer 3042545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer @Override 30527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich public void onTabChanged(String tabId) { 30627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (mAttached) { 30727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich FragmentTransaction ft = doTabChanged(tabId, null); 30827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (ft != null) { 30927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft.commit(); 31027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 31127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 31227f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (mOnTabChangeListener != null) { 31327f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mOnTabChangeListener.onTabChanged(tabId); 31427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 31527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 31627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 31727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) { 31827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich TabInfo newTab = null; 31927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich for (int i=0; i<mTabs.size(); i++) { 32027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich TabInfo tab = mTabs.get(i); 32127f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (tab.tag.equals(tabId)) { 3222545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer newTab = tab; 3232545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 3242545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 32527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (newTab == null) { 32627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich throw new IllegalStateException("No tab known for tag " + tabId); 32727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 32827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (mLastTab != newTab) { 32927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (ft == null) { 33027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft = mFragmentManager.beginTransaction(); 3312545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer } 3322545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer if (mLastTab != null) { 3332545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer if (mLastTab.fragment != null) { 33427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich ft.detach(mLastTab.fragment); 33517045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer } 33627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 33727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (newTab != null) { 33827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich if (newTab.fragment == null) { 33917045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer newTab.fragment = Fragment.instantiate(mContext, 34017045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer newTab.clss.getName(), newTab.args); 34117045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer ft.add(mContainerId, newTab.fragment, newTab.tag); 34217045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer } else { 34317045a16575ece34cfadb63da4791f115625df78Thomas Tafertshofer ft.attach(newTab.fragment); 34427f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 34527f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 34627f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich 34727f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich mLastTab = newTab; 34827f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 34927f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich return ft; 35027f8002e591b5c579f75b2580183b5d1c4219cd4Jack Palevich } 3512545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer} 3522545b32ced69100fe70685b95315c6adf411083bThomas Tafertshofer