• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 
17 package android.widget;
18 
19 import com.android.internal.R;
20 
21 import android.app.LocalActivityManager;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.res.TypedArray;
25 import android.graphics.drawable.Drawable;
26 import android.os.Build;
27 import android.text.TextUtils;
28 import android.util.AttributeSet;
29 import android.view.KeyEvent;
30 import android.view.LayoutInflater;
31 import android.view.SoundEffectConstants;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.view.ViewTreeObserver;
35 import android.view.Window;
36 import android.view.accessibility.AccessibilityEvent;
37 import android.view.accessibility.AccessibilityNodeInfo;
38 
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 /**
43  * Container for a tabbed window view. This object holds two children: a set of tab labels that the
44  * user clicks to select a specific tab, and a FrameLayout object that displays the contents of that
45  * page. The individual elements are typically controlled using this container object, rather than
46  * setting values on the child elements themselves.
47  *
48  */
49 public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchModeChangeListener {
50 
51     private TabWidget mTabWidget;
52     private FrameLayout mTabContent;
53     private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2);
54     /**
55      * This field should be made private, so it is hidden from the SDK.
56      * {@hide}
57      */
58     protected int mCurrentTab = -1;
59     private View mCurrentView = null;
60     /**
61      * This field should be made private, so it is hidden from the SDK.
62      * {@hide}
63      */
64     protected LocalActivityManager mLocalActivityManager = null;
65     private OnTabChangeListener mOnTabChangeListener;
66     private OnKeyListener mTabKeyListener;
67 
68     private int mTabLayoutId;
69 
TabHost(Context context)70     public TabHost(Context context) {
71         super(context);
72         initTabHost();
73     }
74 
TabHost(Context context, AttributeSet attrs)75     public TabHost(Context context, AttributeSet attrs) {
76         super(context, attrs);
77 
78         TypedArray a = context.obtainStyledAttributes(attrs,
79                 com.android.internal.R.styleable.TabWidget,
80                 com.android.internal.R.attr.tabWidgetStyle, 0);
81 
82         mTabLayoutId = a.getResourceId(R.styleable.TabWidget_tabLayout, 0);
83         a.recycle();
84 
85         if (mTabLayoutId == 0) {
86             // In case the tabWidgetStyle does not inherit from Widget.TabWidget and tabLayout is
87             // not defined.
88             mTabLayoutId = R.layout.tab_indicator_holo;
89         }
90 
91         initTabHost();
92     }
93 
initTabHost()94     private void initTabHost() {
95         setFocusableInTouchMode(true);
96         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
97 
98         mCurrentTab = -1;
99         mCurrentView = null;
100     }
101 
102     /**
103      * Get a new {@link TabSpec} associated with this tab host.
104      * @param tag required tag of tab.
105      */
newTabSpec(String tag)106     public TabSpec newTabSpec(String tag) {
107         return new TabSpec(tag);
108     }
109 
110 
111 
112     /**
113       * <p>Call setup() before adding tabs if loading TabHost using findViewById().
114       * <i><b>However</i></b>: You do not need to call setup() after getTabHost()
115       * in {@link android.app.TabActivity TabActivity}.
116       * Example:</p>
117 <pre>mTabHost = (TabHost)findViewById(R.id.tabhost);
118 mTabHost.setup();
119 mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
120       */
setup()121     public void setup() {
122         mTabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
123         if (mTabWidget == null) {
124             throw new RuntimeException(
125                     "Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'");
126         }
127 
128         // KeyListener to attach to all tabs. Detects non-navigation keys
129         // and relays them to the tab content.
130         mTabKeyListener = new OnKeyListener() {
131             public boolean onKey(View v, int keyCode, KeyEvent event) {
132                 switch (keyCode) {
133                     case KeyEvent.KEYCODE_DPAD_CENTER:
134                     case KeyEvent.KEYCODE_DPAD_LEFT:
135                     case KeyEvent.KEYCODE_DPAD_RIGHT:
136                     case KeyEvent.KEYCODE_DPAD_UP:
137                     case KeyEvent.KEYCODE_DPAD_DOWN:
138                     case KeyEvent.KEYCODE_ENTER:
139                         return false;
140 
141                 }
142                 mTabContent.requestFocus(View.FOCUS_FORWARD);
143                 return mTabContent.dispatchKeyEvent(event);
144             }
145 
146         };
147 
148         mTabWidget.setTabSelectionListener(new TabWidget.OnTabSelectionChanged() {
149             public void onTabSelectionChanged(int tabIndex, boolean clicked) {
150                 setCurrentTab(tabIndex);
151                 if (clicked) {
152                     mTabContent.requestFocus(View.FOCUS_FORWARD);
153                 }
154             }
155         });
156 
157         mTabContent = (FrameLayout) findViewById(com.android.internal.R.id.tabcontent);
158         if (mTabContent == null) {
159             throw new RuntimeException(
160                     "Your TabHost must have a FrameLayout whose id attribute is "
161                             + "'android.R.id.tabcontent'");
162         }
163     }
164 
165     @Override
sendAccessibilityEvent(int eventType)166     public void sendAccessibilityEvent(int eventType) {
167         /* avoid super class behavior - TabWidget sends the right events */
168     }
169 
170     /**
171      * If you are using {@link TabSpec#setContent(android.content.Intent)}, this
172      * must be called since the activityGroup is needed to launch the local activity.
173      *
174      * This is done for you if you extend {@link android.app.TabActivity}.
175      * @param activityGroup Used to launch activities for tab content.
176      */
setup(LocalActivityManager activityGroup)177     public void setup(LocalActivityManager activityGroup) {
178         setup();
179         mLocalActivityManager = activityGroup;
180     }
181 
182 
183     @Override
onAttachedToWindow()184     protected void onAttachedToWindow() {
185         super.onAttachedToWindow();
186         final ViewTreeObserver treeObserver = getViewTreeObserver();
187         treeObserver.addOnTouchModeChangeListener(this);
188     }
189 
190     @Override
onDetachedFromWindow()191     protected void onDetachedFromWindow() {
192         super.onDetachedFromWindow();
193         final ViewTreeObserver treeObserver = getViewTreeObserver();
194         treeObserver.removeOnTouchModeChangeListener(this);
195     }
196 
197     /**
198      * {@inheritDoc}
199      */
onTouchModeChanged(boolean isInTouchMode)200     public void onTouchModeChanged(boolean isInTouchMode) {
201         if (!isInTouchMode) {
202             // leaving touch mode.. if nothing has focus, let's give it to
203             // the indicator of the current tab
204             if (mCurrentView != null && (!mCurrentView.hasFocus() || mCurrentView.isFocused())) {
205                 mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
206             }
207         }
208     }
209 
210     /**
211      * Add a tab.
212      * @param tabSpec Specifies how to create the indicator and content.
213      */
addTab(TabSpec tabSpec)214     public void addTab(TabSpec tabSpec) {
215 
216         if (tabSpec.mIndicatorStrategy == null) {
217             throw new IllegalArgumentException("you must specify a way to create the tab indicator.");
218         }
219 
220         if (tabSpec.mContentStrategy == null) {
221             throw new IllegalArgumentException("you must specify a way to create the tab content");
222         }
223         View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();
224         tabIndicator.setOnKeyListener(mTabKeyListener);
225 
226         // If this is a custom view, then do not draw the bottom strips for
227         // the tab indicators.
228         if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) {
229             mTabWidget.setStripEnabled(false);
230         }
231 
232         mTabWidget.addView(tabIndicator);
233         mTabSpecs.add(tabSpec);
234 
235         if (mCurrentTab == -1) {
236             setCurrentTab(0);
237         }
238     }
239 
240 
241     /**
242      * Removes all tabs from the tab widget associated with this tab host.
243      */
clearAllTabs()244     public void clearAllTabs() {
245         mTabWidget.removeAllViews();
246         initTabHost();
247         mTabContent.removeAllViews();
248         mTabSpecs.clear();
249         requestLayout();
250         invalidate();
251     }
252 
getTabWidget()253     public TabWidget getTabWidget() {
254         return mTabWidget;
255     }
256 
getCurrentTab()257     public int getCurrentTab() {
258         return mCurrentTab;
259     }
260 
getCurrentTabTag()261     public String getCurrentTabTag() {
262         if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
263             return mTabSpecs.get(mCurrentTab).getTag();
264         }
265         return null;
266     }
267 
getCurrentTabView()268     public View getCurrentTabView() {
269         if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
270             return mTabWidget.getChildTabViewAt(mCurrentTab);
271         }
272         return null;
273     }
274 
getCurrentView()275     public View getCurrentView() {
276         return mCurrentView;
277     }
278 
setCurrentTabByTag(String tag)279     public void setCurrentTabByTag(String tag) {
280         int i;
281         for (i = 0; i < mTabSpecs.size(); i++) {
282             if (mTabSpecs.get(i).getTag().equals(tag)) {
283                 setCurrentTab(i);
284                 break;
285             }
286         }
287     }
288 
289     /**
290      * Get the FrameLayout which holds tab content
291      */
getTabContentView()292     public FrameLayout getTabContentView() {
293         return mTabContent;
294     }
295 
296     @Override
dispatchKeyEvent(KeyEvent event)297     public boolean dispatchKeyEvent(KeyEvent event) {
298         final boolean handled = super.dispatchKeyEvent(event);
299 
300         // unhandled key ups change focus to tab indicator for embedded activities
301         // when there is nothing that will take focus from default focus searching
302         if (!handled
303                 && (event.getAction() == KeyEvent.ACTION_DOWN)
304                 && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP)
305                 && (mCurrentView != null)
306                 && (mCurrentView.isRootNamespace())
307                 && (mCurrentView.hasFocus())
308                 && (mCurrentView.findFocus().focusSearch(View.FOCUS_UP) == null)) {
309             mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
310             playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
311             return true;
312         }
313         return handled;
314     }
315 
316 
317     @Override
dispatchWindowFocusChanged(boolean hasFocus)318     public void dispatchWindowFocusChanged(boolean hasFocus) {
319         if (mCurrentView != null){
320             mCurrentView.dispatchWindowFocusChanged(hasFocus);
321         }
322     }
323 
324     @Override
onInitializeAccessibilityEvent(AccessibilityEvent event)325     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
326         super.onInitializeAccessibilityEvent(event);
327         event.setClassName(TabHost.class.getName());
328     }
329 
330     @Override
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)331     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
332         super.onInitializeAccessibilityNodeInfo(info);
333         info.setClassName(TabHost.class.getName());
334     }
335 
setCurrentTab(int index)336     public void setCurrentTab(int index) {
337         if (index < 0 || index >= mTabSpecs.size()) {
338             return;
339         }
340 
341         if (index == mCurrentTab) {
342             return;
343         }
344 
345         // notify old tab content
346         if (mCurrentTab != -1) {
347             mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed();
348         }
349 
350         mCurrentTab = index;
351         final TabHost.TabSpec spec = mTabSpecs.get(index);
352 
353         // Call the tab widget's focusCurrentTab(), instead of just
354         // selecting the tab.
355         mTabWidget.focusCurrentTab(mCurrentTab);
356 
357         // tab content
358         mCurrentView = spec.mContentStrategy.getContentView();
359 
360         if (mCurrentView.getParent() == null) {
361             mTabContent
362                     .addView(
363                             mCurrentView,
364                             new ViewGroup.LayoutParams(
365                                     ViewGroup.LayoutParams.MATCH_PARENT,
366                                     ViewGroup.LayoutParams.MATCH_PARENT));
367         }
368 
369         if (!mTabWidget.hasFocus()) {
370             // if the tab widget didn't take focus (likely because we're in touch mode)
371             // give the current tab content view a shot
372             mCurrentView.requestFocus();
373         }
374 
375         //mTabContent.requestFocus(View.FOCUS_FORWARD);
376         invokeOnTabChangeListener();
377     }
378 
379     /**
380      * Register a callback to be invoked when the selected state of any of the items
381      * in this list changes
382      * @param l
383      * The callback that will run
384      */
setOnTabChangedListener(OnTabChangeListener l)385     public void setOnTabChangedListener(OnTabChangeListener l) {
386         mOnTabChangeListener = l;
387     }
388 
invokeOnTabChangeListener()389     private void invokeOnTabChangeListener() {
390         if (mOnTabChangeListener != null) {
391             mOnTabChangeListener.onTabChanged(getCurrentTabTag());
392         }
393     }
394 
395     /**
396      * Interface definition for a callback to be invoked when tab changed
397      */
398     public interface OnTabChangeListener {
onTabChanged(String tabId)399         void onTabChanged(String tabId);
400     }
401 
402 
403     /**
404      * Makes the content of a tab when it is selected. Use this if your tab
405      * content needs to be created on demand, i.e. you are not showing an
406      * existing view or starting an activity.
407      */
408     public interface TabContentFactory {
409         /**
410          * Callback to make the tab contents
411          *
412          * @param tag
413          *            Which tab was selected.
414          * @return The view to display the contents of the selected tab.
415          */
createTabContent(String tag)416         View createTabContent(String tag);
417     }
418 
419 
420     /**
421      * A tab has a tab indicator, content, and a tag that is used to keep
422      * track of it.  This builder helps choose among these options.
423      *
424      * For the tab indicator, your choices are:
425      * 1) set a label
426      * 2) set a label and an icon
427      *
428      * For the tab content, your choices are:
429      * 1) the id of a {@link View}
430      * 2) a {@link TabContentFactory} that creates the {@link View} content.
431      * 3) an {@link Intent} that launches an {@link android.app.Activity}.
432      */
433     public class TabSpec {
434 
435         private String mTag;
436 
437         private IndicatorStrategy mIndicatorStrategy;
438         private ContentStrategy mContentStrategy;
439 
TabSpec(String tag)440         private TabSpec(String tag) {
441             mTag = tag;
442         }
443 
444         /**
445          * Specify a label as the tab indicator.
446          */
setIndicator(CharSequence label)447         public TabSpec setIndicator(CharSequence label) {
448             mIndicatorStrategy = new LabelIndicatorStrategy(label);
449             return this;
450         }
451 
452         /**
453          * Specify a label and icon as the tab indicator.
454          */
setIndicator(CharSequence label, Drawable icon)455         public TabSpec setIndicator(CharSequence label, Drawable icon) {
456             mIndicatorStrategy = new LabelAndIconIndicatorStrategy(label, icon);
457             return this;
458         }
459 
460         /**
461          * Specify a view as the tab indicator.
462          */
setIndicator(View view)463         public TabSpec setIndicator(View view) {
464             mIndicatorStrategy = new ViewIndicatorStrategy(view);
465             return this;
466         }
467 
468         /**
469          * Specify the id of the view that should be used as the content
470          * of the tab.
471          */
setContent(int viewId)472         public TabSpec setContent(int viewId) {
473             mContentStrategy = new ViewIdContentStrategy(viewId);
474             return this;
475         }
476 
477         /**
478          * Specify a {@link android.widget.TabHost.TabContentFactory} to use to
479          * create the content of the tab.
480          */
setContent(TabContentFactory contentFactory)481         public TabSpec setContent(TabContentFactory contentFactory) {
482             mContentStrategy = new FactoryContentStrategy(mTag, contentFactory);
483             return this;
484         }
485 
486         /**
487          * Specify an intent to use to launch an activity as the tab content.
488          */
setContent(Intent intent)489         public TabSpec setContent(Intent intent) {
490             mContentStrategy = new IntentContentStrategy(mTag, intent);
491             return this;
492         }
493 
494 
getTag()495         public String getTag() {
496             return mTag;
497         }
498     }
499 
500     /**
501      * Specifies what you do to create a tab indicator.
502      */
503     private static interface IndicatorStrategy {
504 
505         /**
506          * Return the view for the indicator.
507          */
createIndicatorView()508         View createIndicatorView();
509     }
510 
511     /**
512      * Specifies what you do to manage the tab content.
513      */
514     private static interface ContentStrategy {
515 
516         /**
517          * Return the content view.  The view should may be cached locally.
518          */
getContentView()519         View getContentView();
520 
521         /**
522          * Perhaps do something when the tab associated with this content has
523          * been closed (i.e make it invisible, or remove it).
524          */
tabClosed()525         void tabClosed();
526     }
527 
528     /**
529      * How to create a tab indicator that just has a label.
530      */
531     private class LabelIndicatorStrategy implements IndicatorStrategy {
532 
533         private final CharSequence mLabel;
534 
LabelIndicatorStrategy(CharSequence label)535         private LabelIndicatorStrategy(CharSequence label) {
536             mLabel = label;
537         }
538 
createIndicatorView()539         public View createIndicatorView() {
540             final Context context = getContext();
541             LayoutInflater inflater =
542                     (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
543             View tabIndicator = inflater.inflate(mTabLayoutId,
544                     mTabWidget, // tab widget is the parent
545                     false); // no inflate params
546 
547             final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
548             tv.setText(mLabel);
549 
550             if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
551                 // Donut apps get old color scheme
552                 tabIndicator.setBackgroundResource(R.drawable.tab_indicator_v4);
553                 tv.setTextColor(context.getResources().getColorStateList(R.color.tab_indicator_text_v4));
554             }
555 
556             return tabIndicator;
557         }
558     }
559 
560     /**
561      * How we create a tab indicator that has a label and an icon
562      */
563     private class LabelAndIconIndicatorStrategy implements IndicatorStrategy {
564 
565         private final CharSequence mLabel;
566         private final Drawable mIcon;
567 
LabelAndIconIndicatorStrategy(CharSequence label, Drawable icon)568         private LabelAndIconIndicatorStrategy(CharSequence label, Drawable icon) {
569             mLabel = label;
570             mIcon = icon;
571         }
572 
createIndicatorView()573         public View createIndicatorView() {
574             final Context context = getContext();
575             LayoutInflater inflater =
576                     (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
577             View tabIndicator = inflater.inflate(mTabLayoutId,
578                     mTabWidget, // tab widget is the parent
579                     false); // no inflate params
580 
581             final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
582             final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
583 
584             // when icon is gone by default, we're in exclusive mode
585             final boolean exclusive = iconView.getVisibility() == View.GONE;
586             final boolean bindIcon = !exclusive || TextUtils.isEmpty(mLabel);
587 
588             tv.setText(mLabel);
589 
590             if (bindIcon && mIcon != null) {
591                 iconView.setImageDrawable(mIcon);
592                 iconView.setVisibility(VISIBLE);
593             }
594 
595             if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
596                 // Donut apps get old color scheme
597                 tabIndicator.setBackgroundResource(R.drawable.tab_indicator_v4);
598                 tv.setTextColor(context.getResources().getColorStateList(R.color.tab_indicator_text_v4));
599             }
600 
601             return tabIndicator;
602         }
603     }
604 
605     /**
606      * How to create a tab indicator by specifying a view.
607      */
608     private class ViewIndicatorStrategy implements IndicatorStrategy {
609 
610         private final View mView;
611 
ViewIndicatorStrategy(View view)612         private ViewIndicatorStrategy(View view) {
613             mView = view;
614         }
615 
createIndicatorView()616         public View createIndicatorView() {
617             return mView;
618         }
619     }
620 
621     /**
622      * How to create the tab content via a view id.
623      */
624     private class ViewIdContentStrategy implements ContentStrategy {
625 
626         private final View mView;
627 
ViewIdContentStrategy(int viewId)628         private ViewIdContentStrategy(int viewId) {
629             mView = mTabContent.findViewById(viewId);
630             if (mView != null) {
631                 mView.setVisibility(View.GONE);
632             } else {
633                 throw new RuntimeException("Could not create tab content because " +
634                         "could not find view with id " + viewId);
635             }
636         }
637 
getContentView()638         public View getContentView() {
639             mView.setVisibility(View.VISIBLE);
640             return mView;
641         }
642 
tabClosed()643         public void tabClosed() {
644             mView.setVisibility(View.GONE);
645         }
646     }
647 
648     /**
649      * How tab content is managed using {@link TabContentFactory}.
650      */
651     private class FactoryContentStrategy implements ContentStrategy {
652         private View mTabContent;
653         private final CharSequence mTag;
654         private TabContentFactory mFactory;
655 
FactoryContentStrategy(CharSequence tag, TabContentFactory factory)656         public FactoryContentStrategy(CharSequence tag, TabContentFactory factory) {
657             mTag = tag;
658             mFactory = factory;
659         }
660 
getContentView()661         public View getContentView() {
662             if (mTabContent == null) {
663                 mTabContent = mFactory.createTabContent(mTag.toString());
664             }
665             mTabContent.setVisibility(View.VISIBLE);
666             return mTabContent;
667         }
668 
tabClosed()669         public void tabClosed() {
670             mTabContent.setVisibility(View.GONE);
671         }
672     }
673 
674     /**
675      * How tab content is managed via an {@link Intent}: the content view is the
676      * decorview of the launched activity.
677      */
678     private class IntentContentStrategy implements ContentStrategy {
679 
680         private final String mTag;
681         private final Intent mIntent;
682 
683         private View mLaunchedView;
684 
IntentContentStrategy(String tag, Intent intent)685         private IntentContentStrategy(String tag, Intent intent) {
686             mTag = tag;
687             mIntent = intent;
688         }
689 
getContentView()690         public View getContentView() {
691             if (mLocalActivityManager == null) {
692                 throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?");
693             }
694             final Window w = mLocalActivityManager.startActivity(
695                     mTag, mIntent);
696             final View wd = w != null ? w.getDecorView() : null;
697             if (mLaunchedView != wd && mLaunchedView != null) {
698                 if (mLaunchedView.getParent() != null) {
699                     mTabContent.removeView(mLaunchedView);
700                 }
701             }
702             mLaunchedView = wd;
703 
704             // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so they can get
705             // focus if none of their children have it. They need focus to be able to
706             // display menu items.
707             //
708             // Replace this with something better when Bug 628886 is fixed...
709             //
710             if (mLaunchedView != null) {
711                 mLaunchedView.setVisibility(View.VISIBLE);
712                 mLaunchedView.setFocusableInTouchMode(true);
713                 ((ViewGroup) mLaunchedView).setDescendantFocusability(
714                         FOCUS_AFTER_DESCENDANTS);
715             }
716             return mLaunchedView;
717         }
718 
tabClosed()719         public void tabClosed() {
720             if (mLaunchedView != null) {
721                 mLaunchedView.setVisibility(View.GONE);
722             }
723         }
724     }
725 
726 }
727