Android的FragmentTabHost - 未完全成熟了吗? [英] Android FragmentTabHost - Not fully baked yet?

查看:148
本文介绍了Android的FragmentTabHost - 未完全成熟了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想看看是否有人曾与使用FragmentTabHost附带的新的Andr​​oid API级标签的定制成功17.

我很高兴能到鸟巢在我ViewPager SherlockFragments一个tabHost,但是我无法做简单的事情,如移动标签的底部或改变标签的布局。

有没有人见过使用这个功能的一个很好的例子吗?

这是唯一的例子我能找到在Android文档,和孤单几乎没有什么介绍了它的使用。这也似乎忽略无论是在布局中定义的 R.id.fragment1

我的问题,我想是有没有人碰到一个很好的教程回复:FragmentTabHost 或者如果他们对如何一)把嵌套的标签在底部或b)改变所述片的布局的想法。

我已经尝试了所有的常用方法,但因为它出现在XML布局文件被覆盖,我没有多少运气。

 私人FragmentTabHost mTab​​Host;

@覆盖
公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
        捆绑savedInstanceState){

    的setContentView(R.layout.fragment_tabs);
    mTabHost =(FragmentTabHost)findViewById(android.R.id.tabhost);
    mTabHost.setup(这一点,getSupportFragmentManager(),R.id.realtabcontent);

    mTabHost.addTab(mTabHost.newTabSpec(简单)。setIndicator(简单),
            FragmentStackSupport.CountingFragment.class,NULL);
    mTabHost.addTab(mTabHost.newTabSpec(接触)。setIndicator(联系人),
            LoaderCursorSupport.CursorLoaderListFragment.class,NULL);
    mTabHost.addTab(mTabHost.newTabSpec(定制)。setIndicator(自定义),
            LoaderCustomSupport.AppListFragment.class,NULL);
    mTabHost.addTab(mTabHost.newTabSpec(节流)。setIndicator(节流),
            LoaderThrottleSupport.ThrottledLoaderListFragment.class,NULL);

    返回mTabHost;
}
 

之后做一些研究,它似乎有可能与初始化FragmentTabHost的支持库毛刺。用户在这里对谷歌code 提供了一个建议,这

FragmentTabHost.java

 私人无效initFragmentTabHost(上下文的背景下,ATTRS的AttributeSet){
    TypedArray A = context.obtainStyledAttributes(ATTRS,
            新INT [] {android.R.attr.inflatedId},0,0);
    mContainerId = a.getResourceId(0,0);
    a.recycle();

    super.setOnTabChangedListener(本);

    //如果车主一直没有作出了自己的视图层次,然后作为一种方便
    //我们将在这里建立一个标准。


/ *****这里评论code,因为findViewById(android.R.id.tabs)EVERY TIME IS NULL我们有自己的布局****** //


//如果(findViewById(android.R.id.tabs)== NULL){
//的LinearLayout LL =新的LinearLayout(上下文);
// ll.setOrientation(LinearLayout.VERTICAL);
// addView(LL,新FrameLayout.LayoutParams(
// ViewGroup.LayoutParams.FILL_PARENT,
// ViewGroup.LayoutParams.FILL_PARENT));
//
// TabWidget TW =新TabWidget(上下文);
// tw.setId(android.R.id.tabs);
// tw.setOrientation(TabWidget.HORIZONTAL);
// ll.addView(TW,新LinearLayout.LayoutParams(
// ViewGroup.LayoutParams.FILL_PARENT,
// ViewGroup.LayoutParams.WRAP_CONTENT,0));
//
//的FrameLayout FL =新的FrameLayout(上下文);
// fl.setId(android.R.id.tabcontent);
// ll.addView(佛罗里达州,新LinearLayout.LayoutParams(0,0,0));
//
// mRealTabContent = FL =新的FrameLayout(上下文);
// mRealTabContent.setId(mContainerId);
// ll.addView(佛罗里达州,新LinearLayout.LayoutParams(
// LinearLayout.LayoutParams.FILL_PARENT,0,1));
//}
}
 

XML布局片段:

 < android.support.v4.app.FragmentTabHost
的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
机器人:ID =@机器人:ID / tabhost
机器人:layout_width =match_parent
机器人:layout_height =match_parent>
<的LinearLayout
    机器人:方向=垂直
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>
    <的FrameLayout
        机器人:ID =@机器人:ID / tabcontent
        机器人:layout_width =0dp
        机器人:layout_height =0dp
        机器人:layout_weight =0/>
    <的FrameLayout
        机器人:ID =@ + ID / realtabcontent
        机器人:layout_width =match_parent
        机器人:layout_height =0dp
        机器人:layout_weight =1/>
    < TabWidget
        机器人:ID =@机器人:ID /标签
        机器人:方向=横向
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_weight =0/>

< / LinearLayout中>
< /android.support.v4.app.FragmentTabHost>
 

解决方案

我终于到了这条底线。有一个问题FragmentTabHost.java这将总是创建一个TabHost的元素对你来说,不管你的XML定义和膨胀事先。

因此​​,我写我自己的版本FragmentTabHost.java时注释掉code部分。

请务必使用这个新的版本,在你的XML布局,< com.example.app.MyFragmentTabHost

当然它充气:

Fragment1.java:

  mTab​​Host =(MyFragmentTabHost)view.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(),getChildFragmentManager(),android.R.id.tabcontent);
 

MyFragmentTabHost.java:

 包com.example.app;

进口的java.util.ArrayList;

进口android.content.Context;
进口android.content.res.TypedArray;
进口android.os.Bundle;
进口android.os.Parcel;
进口android.os.Parcelable;
进口android.support.v4.app.Fragment;
进口android.support.v4.app.FragmentManager;
进口android.support.v4.app.FragmentTransaction;
进口android.util.AttributeSet;
进口android.view.View;
进口android.widget.FrameLayout;
进口android.widget.TabHost;

/ **
 *特别TabHost,允许使用{@link片段}对象为
 *它的标签内容。当在一个视图层次结构将这个,充气后
 *您必须调用层次{@link #setup(背景下,FragmentManager,INT)}
 *以完成标签主机的初始化。
 *
 * /
公共类MyFragmentTabHost扩展TabHost
    实现TabHost.OnTabChangeListener {
私人最终的ArrayList< TabInfo> mTabs =新的ArrayList< TabInfo>();
私人的FrameLayout mRealTabContent;
私人语境mContext;
私人FragmentManager mFragmentManager;
私人诠释mContainerId;
私人TabHost.OnTabChangeListener mOnTabChangeListener;
私人TabInfo mLastTab;
私人布尔mAttached;

静态final类TabInfo {
    私人最终字符串标记;
    私人最终类别<> CLSS;
    私人最终捆绑的args;
    私人片段片段;

    TabInfo(字符串_tag,类<> _class,捆绑_args){
        标签= _tag;
        CLSS = _class;
        的args = _args;
    }
}

静态类DummyTabFactory实现TabHost.TabContentFactory {
    私人最终语境mContext;

    公共DummyTabFactory(上下文的背景下){
        mContext =背景;
    }

    @覆盖
    公共查看createTabContent(字符串变量){
        视图V =新景(mContext);
        v.setMinimumWidth(0);
        v.setMinimumHeight(0);
        返回伏;
    }
}

静态类SavedState扩展BaseSavedState {
    字符串curTab;

    SavedState(Parcelable超级大国){
        超(超国家);
    }

    私人SavedState(包裹中){
        超级(在);
        curTab = in.readString();
    }

    @覆盖
    公共无效writeToParcel(包裹出来,诠释标志){
        super.writeToParcel(满分,旗);
        out.writeString(curTab);
    }

    @覆盖
    公共字符串的toString(){
        回归FragmentTabHost.SavedState {
                + Integer.toHexString(System.identityHash code(本))
                +curTab =+ curTab +};
    }

    公共静态最终Parcelable.Creator< SavedState> CREATOR
            =新Parcelable.Creator< SavedState>(){
        公共SavedState createFromParcel(包裹中){
            返回新SavedState(中);
        }

        公共SavedState [] newArray(INT尺寸){
            返回新SavedState【尺寸】;
        }
    };
}

公共MyFragmentTabHost(上下文的背景下){
    //请注意,我们通过对接受一个的AttributeSet版本打电话,
    //因为简单的上下文结构可能会导致在一个破碎的对象!
    超(背景下,NULL);
    initFragmentTabHost(背景下,NULL);
}

公共MyFragmentTabHost(上下文的背景下,ATTRS的AttributeSet){
    超(背景下,ATTRS);
    initFragmentTabHost(背景下,ATTRS);
}

私人无效initFragmentTabHost(上下文的背景下,ATTRS的AttributeSet){
    TypedArray A = context.obtainStyledAttributes(ATTRS,
            新INT [] {android.R.attr.inflatedId},0,0);
    mContainerId = a.getResourceId(0,0);
    a.recycle();

    super.setOnTabChangedListener(本);


    / ***删除该功能的其余部分*** /
    / *** findViewById(android.R.id.tabs)IS NULL EVERY TIME *** /
}

/ **
 * @德precated不要叫原TabHost设置,则必须改为
 *电话{@link #setup(背景下,FragmentManager)}或
 * {@link #setup(背景下,FragmentManager,INT)}。
 * /
@覆盖@德precated
公共无效设置(){
    抛出新IllegalStateException异常(
            必须呼叫建立(),需要一个语境和FragmentManager);
}

公共无效设置(上下文的背景下,FragmentManager经理){
    super.setup();
    mContext =背景;
    mFragmentManager =经理;
    ensureContent();
}

公共无效设置(上下文的背景下,FragmentManager经理,诠释containerId){
    super.setup();
    mContext =背景;
    mFragmentManager =经理;
    mContainerId = containerId;
    ensureContent();
    mRealTabContent.setId(containerId);

    //我们必须有一个ID,以便能够保存/恢复我们的国家。如果
    //店主并没有设置一个在这一点上,我们将它设置我们自己。
    如果(的getId()== View.NO_ID){
        SETID(android.R.id.tabhost);
    }
}

私人无效ensureContent(){
    如果(mRealTabContent == NULL){
        mRealTabContent =(的FrameLayout)findViewById(mContainerId);
        如果(mRealTabContent == NULL){
            抛出新IllegalStateException异常(
                    无标签内容的FrameLayout发现号+ mContainerId);
        }
    }
}

@覆盖
公共无效setOnTabChangedListener(OnTabChangeListener L){
    mOnTabChangeListener =升;
}

公共无效addTab(TabHost.TabSpec则tabspec,类<> CLSS,捆绑参数){
    tabSpec.setContent(新DummyTabFactory(mContext));
    字符串变量= tabSpec.getTag();

    TabInfo信息=新TabInfo(标签,CLSS,参数);

    如果(mAttached){
        //如果我们已经贴在窗户上,然后进行检查,以
        //确保该选项卡的片段是无效的,如果它的存在。这不应该
        //通常发生。
        info.fragment = mFragmentManager.findFragmentByTag(标签);
        如果(info.fragment =空&安培;!&安培;!info.fragment.isDetached()){
            FragmentTransaction英尺= mFragmentManager.beginTransaction();
            ft.detach(info.fragment);
            ft.commit();
        }
    }

    mTabs.add(信息);
    addTab(则tabspec);
}

@覆盖
保护无效onAttachedToWindow(){
    super.onAttachedToWindow();

    串currentTab = getCurrentTabTag();

    //遍历所有选项卡,并确保他们的片段匹配
    //正确的状态。
    FragmentTransaction英尺= NULL;
    的for(int i = 0; I< mTab​​s.size();我++){
        TabInfo标签= mTab​​s.get(我);
        tab.fragment = mFragmentManager.findFragmentByTag(tab.tag);
        如果(tab.fragment =空&安培;!&安培;!tab.fragment.isDetached()){
            如果(tab.tag.equals(currentTab)){
                //片段为这个标签已经存在和
                //活跃,这是我们真正想拥有
                //为当前选项卡。没事做。
                mLastTab =标签;
            } 其他 {
                //将该片段恢复在激活状态,
                //而不是当前选项卡。停用。
                如果(英尺== NULL){
                    英尺= mFragmentManager.beginTransaction();
                }
                ft.detach(tab.fragment);
            }
        }
    }

    //我们现在可以走了。确保我们切换到
    //正确的选项卡。
    mAttached = TRUE;
    FT = doTabChanged(currentTab,英尺);
    如果(英尺!= NULL){
        ft.commit();
        mFragmentManager.executePendingTransactions();
    }
}

@覆盖
保护无效onDetachedFromWindow(){
    super.onDetachedFromWindow();
    mAttached = FALSE;
}

@覆盖
保护Parcelable的onSaveInstanceState(){
    Parcelable超级大国= super.onSaveInstanceState();
    SavedState SS =新SavedState(覆);
    ss.curTab = getCurrentTabTag();
    返回SS;
}

@覆盖
保护无效onRestoreInstanceState(Parcelable州){
    SavedState SS =(SavedState)状态;
    super.onRestoreInstanceState(ss.getSuperState());
    setCurrentTabByTag(ss.curTab);
}

@覆盖
公共无效onTabChanged(字符串tabId){
    如果(mAttached){
        FragmentTransaction英尺= doTabChanged(tabId,NULL);
        如果(英尺!= NULL){
            ft.commit();
        }
    }
    如果(mOnTabChangeListener!= NULL){
        mOnTabChangeListener.onTabChanged(tabId);
    }
}

私人FragmentTransaction doTabChanged(字符串tabId,FragmentTransaction英尺){
    TabInfo newTab = NULL;
    的for(int i = 0; I< mTab​​s.size();我++){
        TabInfo标签= mTab​​s.get(我);
        如果(tab.tag.equals(tabId)){
            newTab =标签;
        }
    }
    如果(newTab == NULL){
        抛出新IllegalStateException异常(无标签闻名的标记+ tabId);
    }
    如果(mLastTab!= newTab){
        如果(英尺== NULL){
            英尺= mFragmentManager.beginTransaction();
        }
        如果(mLastTab!= NULL){
            如果(mLastTab.fragment!= NULL){
                ft.detach(mLastTab.fragment);
            }
        }
        如果(newTab!= NULL){
            如果(newTab.fragment == NULL){
                newTab.fragment = Fragment.instantiate(mContext,
                        newTab.clss.getName(),newTab.args);
                ft.add(mContainerId,newTab.fragment,newTab.tag);
            } 其他 {
                ft.attach(newTab.fragment);
            }
        }

        mLastTab = newTab;
    }
    返回英尺;
}
}
 

I wanted to see if anyone has had success with customization of tabs using FragmentTabHost that comes with the new Android API level 17.

I was excited to be able to nest a tabHost within my ViewPager SherlockFragments, but I'm having trouble doing simple things like moving the tabs to the bottom or changing the layout of the tabs.

Has anyone seen a good example of using this functionality?

This is the only example I could find in the Android docs, and theres just about nothing that describes its use. It also seems to ignore whatever is defined in the layout for R.id.fragment1.

My question I suppose would be if anyone has come across a good tutorial re:FragmentTabHost or if they have an idea about how to a) put the nested tabs at the bottom or b) change the layout of said tabs.

I've tried all the usual methods, but since it appears the XML layout file is overridden, I haven't had much luck.

private FragmentTabHost mTabHost;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    setContentView(R.layout.fragment_tabs);
    mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
    mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

    mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
            FragmentStackSupport.CountingFragment.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
            LoaderCursorSupport.CursorLoaderListFragment.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
            LoaderCustomSupport.AppListFragment.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),
            LoaderThrottleSupport.ThrottledLoaderListFragment.class, null);

    return mTabHost;
}

After doing some research, it appears there may be a glitch with initializing the FragmentTabHost in the support library. The user here on Google code has provided a suggestion to this:

FragmentTabHost.java

private void initFragmentTabHost(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs,
            new int[] { android.R.attr.inflatedId }, 0, 0);
    mContainerId = a.getResourceId(0, 0);
    a.recycle();

    super.setOnTabChangedListener(this);

    // If owner hasn't made its own view hierarchy, then as a convenience
    // we will construct a standard one here.


/***** HERE COMMENT CODE BECAUSE findViewById(android.R.id.tabs) EVERY TIME IS NULL WE HAVE OWN         LAYOUT ******//


//        if (findViewById(android.R.id.tabs) == null) {
//            LinearLayout ll = new LinearLayout(context);
//            ll.setOrientation(LinearLayout.VERTICAL);
//            addView(ll, new FrameLayout.LayoutParams(
//                    ViewGroup.LayoutParams.FILL_PARENT,
//                    ViewGroup.LayoutParams.FILL_PARENT));
//
//            TabWidget tw = new TabWidget(context);
//            tw.setId(android.R.id.tabs);
//            tw.setOrientation(TabWidget.HORIZONTAL);
//            ll.addView(tw, new LinearLayout.LayoutParams(
//                    ViewGroup.LayoutParams.FILL_PARENT,
//                    ViewGroup.LayoutParams.WRAP_CONTENT, 0));
//
//            FrameLayout fl = new FrameLayout(context);
//            fl.setId(android.R.id.tabcontent);
//            ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0));
//
//            mRealTabContent = fl = new FrameLayout(context);
//            mRealTabContent.setId(mContainerId);
//            ll.addView(fl, new LinearLayout.LayoutParams(
//                    LinearLayout.LayoutParams.FILL_PARENT, 0, 1));
//        }
}

XML Layout for fragment:

<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">  
    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="0"/>
    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <TabWidget
        android:id="@android:id/tabs"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0"/>

</LinearLayout>
</android.support.v4.app.FragmentTabHost>

解决方案

I finally got to the bottom of this. There is an issue with FragmentTabHost.java which will always create a TabHost element for you, no matter what you define in XML and inflate beforehand.

As such, I commented out that part of code when writing my own version of FragmentTabHost.java.

Make sure to use your new version of this in your XML layout, <com.example.app.MyFragmentTabHost

And of course inflate it:

Fragment1.java:

mTabHost = (MyFragmentTabHost) view.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent);

MyFragmentTabHost.java:

package com.example.app;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TabHost;

/**
 * Special TabHost that allows the use of {@link Fragment} objects for
 * its tab content.  When placing this in a view hierarchy, after inflating
 * the hierarchy you must call {@link #setup(Context, FragmentManager, int)}
 * to complete the initialization of the tab host.
 *
 */
public class MyFragmentTabHost extends TabHost
    implements TabHost.OnTabChangeListener {
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
private FrameLayout mRealTabContent;
private Context mContext;
private FragmentManager mFragmentManager;
private int mContainerId;
private TabHost.OnTabChangeListener mOnTabChangeListener;
private TabInfo mLastTab;
private boolean mAttached;

static final class TabInfo {
    private final String tag;
    private final Class<?> clss;
    private final Bundle args;
    private Fragment fragment;

    TabInfo(String _tag, Class<?> _class, Bundle _args) {
        tag = _tag;
        clss = _class;
        args = _args;
    }
}

static class DummyTabFactory implements TabHost.TabContentFactory {
    private final Context mContext;

    public DummyTabFactory(Context context) {
        mContext = context;
    }

    @Override
    public View createTabContent(String tag) {
        View v = new View(mContext);
        v.setMinimumWidth(0);
        v.setMinimumHeight(0);
        return v;
    }
}

static class SavedState extends BaseSavedState {
    String curTab;

    SavedState(Parcelable superState) {
        super(superState);
    }

    private SavedState(Parcel in) {
        super(in);
        curTab = in.readString();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeString(curTab);
    }

    @Override
    public String toString() {
        return "FragmentTabHost.SavedState{"
                + Integer.toHexString(System.identityHashCode(this))
                + " curTab=" + curTab + "}";
    }

    public static final Parcelable.Creator<SavedState> CREATOR
            = new Parcelable.Creator<SavedState>() {
        public SavedState createFromParcel(Parcel in) {
            return new SavedState(in);
        }

        public SavedState[] newArray(int size) {
            return new SavedState[size];
        }
    };
}

public MyFragmentTabHost(Context context) {
    // Note that we call through to the version that takes an AttributeSet,
    // because the simple Context construct can result in a broken object!
    super(context, null);
    initFragmentTabHost(context, null);
}

public MyFragmentTabHost(Context context, AttributeSet attrs) {
    super(context, attrs);
    initFragmentTabHost(context, attrs);
}

private void initFragmentTabHost(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs,
            new int[] { android.R.attr.inflatedId }, 0, 0);
    mContainerId = a.getResourceId(0, 0);
    a.recycle();

    super.setOnTabChangedListener(this);


    /*** REMOVE THE REST OF THIS FUNCTION ***/
    /*** findViewById(android.R.id.tabs) IS NULL EVERY TIME ***/
}

/**
 * @deprecated Don't call the original TabHost setup, you must instead
 * call {@link #setup(Context, FragmentManager)} or
 * {@link #setup(Context, FragmentManager, int)}.
 */
@Override @Deprecated
public void setup() {
    throw new IllegalStateException(
            "Must call setup() that takes a Context and FragmentManager");
}

public void setup(Context context, FragmentManager manager) {
    super.setup();
    mContext = context;
    mFragmentManager = manager;
    ensureContent();
}

public void setup(Context context, FragmentManager manager, int containerId) {
    super.setup();
    mContext = context;
    mFragmentManager = manager;
    mContainerId = containerId;
    ensureContent();
    mRealTabContent.setId(containerId);

    // We must have an ID to be able to save/restore our state.  If
    // the owner hasn't set one at this point, we will set it ourself.
    if (getId() == View.NO_ID) {
        setId(android.R.id.tabhost);
    }
}

private void ensureContent() {
    if (mRealTabContent == null) {
        mRealTabContent = (FrameLayout)findViewById(mContainerId);
        if (mRealTabContent == null) {
            throw new IllegalStateException(
                    "No tab content FrameLayout found for id " + mContainerId);
        }
    }
}

@Override
public void setOnTabChangedListener(OnTabChangeListener l) {
    mOnTabChangeListener = l;
}

public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
    tabSpec.setContent(new DummyTabFactory(mContext));
    String tag = tabSpec.getTag();

    TabInfo info = new TabInfo(tag, clss, args);

    if (mAttached) {
        // If we are already attached to the window, then check to make
        // sure this tab's fragment is inactive if it exists.  This shouldn't
        // normally happen.
        info.fragment = mFragmentManager.findFragmentByTag(tag);
        if (info.fragment != null && !info.fragment.isDetached()) {
            FragmentTransaction ft = mFragmentManager.beginTransaction();
            ft.detach(info.fragment);
            ft.commit();
        }
    }

    mTabs.add(info);
    addTab(tabSpec);
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    String currentTab = getCurrentTabTag();

    // Go through all tabs and make sure their fragments match
    // the correct state.
    FragmentTransaction ft = null;
    for (int i=0; i<mTabs.size(); i++) {
        TabInfo tab = mTabs.get(i);
        tab.fragment = mFragmentManager.findFragmentByTag(tab.tag);
        if (tab.fragment != null && !tab.fragment.isDetached()) {
            if (tab.tag.equals(currentTab)) {
                // The fragment for this tab is already there and
                // active, and it is what we really want to have
                // as the current tab.  Nothing to do.
                mLastTab = tab;
            } else {
                // This fragment was restored in the active state,
                // but is not the current tab.  Deactivate it.
                if (ft == null) {
                    ft = mFragmentManager.beginTransaction();
                }
                ft.detach(tab.fragment);
            }
        }
    }

    // We are now ready to go.  Make sure we are switched to the
    // correct tab.
    mAttached = true;
    ft = doTabChanged(currentTab, ft);
    if (ft != null) {
        ft.commit();
        mFragmentManager.executePendingTransactions();
    }
}

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    mAttached = false;
}

@Override
protected Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();
    SavedState ss = new SavedState(superState);
    ss.curTab = getCurrentTabTag();
    return ss;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
    SavedState ss = (SavedState)state;
    super.onRestoreInstanceState(ss.getSuperState());
    setCurrentTabByTag(ss.curTab);
}

@Override
public void onTabChanged(String tabId) {
    if (mAttached) {
        FragmentTransaction ft = doTabChanged(tabId, null);
        if (ft != null) {
            ft.commit();
        }
    }
    if (mOnTabChangeListener != null) {
        mOnTabChangeListener.onTabChanged(tabId);
    }
}

private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {
    TabInfo newTab = null;
    for (int i=0; i<mTabs.size(); i++) {
        TabInfo tab = mTabs.get(i);
        if (tab.tag.equals(tabId)) {
            newTab = tab;
        }
    }
    if (newTab == null) {
        throw new IllegalStateException("No tab known for tag " + tabId);
    }
    if (mLastTab != newTab) {
        if (ft == null) {
            ft = mFragmentManager.beginTransaction();
        }
        if (mLastTab != null) {
            if (mLastTab.fragment != null) {
                ft.detach(mLastTab.fragment);
            }
        }
        if (newTab != null) {
            if (newTab.fragment == null) {
                newTab.fragment = Fragment.instantiate(mContext,
                        newTab.clss.getName(), newTab.args);
                ft.add(mContainerId, newTab.fragment, newTab.tag);
            } else {
                ft.attach(newTab.fragment);
            }
        }

        mLastTab = newTab;
    }
    return ft;
}
}

这篇关于Android的FragmentTabHost - 未完全成熟了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆