FragmentTabHost - 没有已知标签为空的标签

几天前,我在 Fragment 中使用 NavigationDrawer 实现了 TabHostFramgent,我遇到了以下错误:

Few days ago I implemented TabHostFramgent in a Fragment with a NavigationDrawer, and I faced with a problem that is the following error :

java.lang.IllegalStateException: No tab known for tag null

java.lang.IllegalStateException: No tab known for tag null

问题是一切都很完美,因为我的 NavigationDrawer 的第一个项目列表是我的 TabHostFragment,所以它运行良好,但问题是当我进入示例时到第二个项目,然后我想回到第一个项目,每次我尝试都会崩溃.

The thing is that all works perfectly since my first item list of my NavigationDrawer is my TabHostFragment, so it works perfect, but the problem is when I go in example to the second item and then I want to go back to the first item, every time that I try so it crashes.

我到处搜索,在 SOcode.google.com 等中...我仍然没有得到正确的答案.

I was searching everywhere, here in SO, code.google.com, etc... and I still don't get the proper answer.

我的 tab_host_test_2.xml看起来像:

  <android.support.v4.app.FragmentTabHost xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" />

        <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="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

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

我的 activity_main.xml 我的 NavigationDrawer 看起来像:

My activity_main.xml where I've got my NavigationDrawer looks like :

 <android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Framelayout to display Fragments -->
    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


    <!-- Listview to display slider menu -->
    <ListView
        android:id="@+id/list_slidermenu"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@color/list_divider"
        android:dividerHeight="1dp"
        android:listSelector="@drawable/list_selector"
        android:background="@color/list_background"/>
</android.support.v4.widget.DrawerLayout>

我的TabHostFragment.java:

    public class TabHostFragment extends Fragment {

    public TabHostFragment(){

    }
    private FragmentTabHost mTabHost;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.tab_host_test2, container, false);
        return rootView;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        mTabHost = (FragmentTabHost)view.findViewById(android.R.id.tabhost);
        mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);

        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab1"),
                MisOfertasFragment.class, null);
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Tab2"),
                RecomendacionesFragment.class, null);




    }

}

我的ActivityMain.java:

public class MainActivity extends FragmentActivity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    // saber si esta abierto
    public boolean mDrawerOpened;
    // nav drawer title
    private CharSequence mDrawerTitle;
    private FragmentTabHost mTabHost;
    // used to store app title
    private CharSequence mTitle;

    //para ponerlo visible
    public MenuItem mi;

    // slide menu items
    private String[] navMenuTitles;
    private TypedArray navMenuIcons;

    private ArrayList<NavDrawerItem> navDrawerItems;
    private NavDrawerListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        mTitle = mDrawerTitle = getTitle();

        // load slide menu items
        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);

        // nav drawer icons from resources
        navMenuIcons = getResources()
                .obtainTypedArray(R.array.nav_drawer_icons);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.list_slidermenu);

        navDrawerItems = new ArrayList<NavDrawerItem>();

        // adding nav drawer items to array
        // Home
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[0], navMenuIcons.getResourceId(0, -1)));
        // Find People
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[1], navMenuIcons.getResourceId(1, -1)));
        // Photos
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[2], navMenuIcons.getResourceId(2, -1)));
        // Communities, Will add a counter here
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[3], navMenuIcons.getResourceId(3, -1)));
        // Pages
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[4], navMenuIcons.getResourceId(4, -1)));
        // What's hot, We  will add a counter here
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[5], navMenuIcons.getResourceId(5, -1)));
        //AyudaSugerencias
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[6], navMenuIcons.getResourceId(6, -1)));
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[7], navMenuIcons.getResourceId(7, -1)));


        // Recycle the typed array
        navMenuIcons.recycle();

        mDrawerList.setOnItemClickListener(new SlideMenuClickListener());

        // setting the nav drawer list adapter
        adapter = new NavDrawerListAdapter(getApplicationContext(),
                navDrawerItems);
        mDrawerList.setAdapter(adapter);

        // enabling action bar app icon and behaving it as toggle button

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setBackgroundDrawable(new ColorDrawable(0xff1d97dd));
        getActionBar().setHomeButtonEnabled(true);

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                R.drawable.ic_drawer, //nav menu toggle icon
                R.string.app_name, // nav drawer open - description for accessibility
                R.string.app_name // nav drawer close - description for accessibility
        ) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(
                        Html.fromHtml("<font color='ffffff'>"
                                + mTitle + "</font>"));

                // calling onPrepareOptionsMenu() to show action bar icons
                invalidateOptionsMenu();
                mDrawerOpened = false;
                syncState();

            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(
                        Html.fromHtml("<font color='ffffff'>"
                                + mDrawerTitle + "</font>"));

                // calling onPrepareOptionsMenu() to hide action bar icons
                invalidateOptionsMenu();
                mDrawerOpened = true;
                syncState();
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if (savedInstanceState == null) {
            // on first time display view for first nav item
            displayView(0);
        }
    }

    /**
     * Slide menu item click listener
     */
    private class SlideMenuClickListener implements
            ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                                long id) {
            // display view for selected nav drawer item
            displayView(position);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {


        getMenuInflater().inflate(R.menu.main, menu);


        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Fragment fragment = null;
        // toggle nav drawer on selecting action bar app icon/title
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle action bar actions click
        switch (item.getItemId()) {
            case R.id.action_settings:
                return true;
            case R.id.ofertasRefresh:
                return true;
            case R.id.menu_search:
                return true;
            case R.id.newOffer:
                getFragmentManager().beginTransaction().replace(R.id.frame_container, new TipusNouProducte()).commit();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    /* *
     * Called when invalidateOptionsMenu() is triggered
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // if nav drawer is opened, hide the action items
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
        if (mDrawerOpened) {
            menu.removeItem(R.id.ofertasRefresh);
            menu.removeItem(R.id.menu_search);
            menu.removeItem(R.id.newOffer);
        }
        if (!mDrawerOpened) {
            menu.add(Menu.NONE, R.id.ofertasRefresh, Menu.NONE, mTitle);
        }
        return super.onPrepareOptionsMenu(menu);

    }

    /**
     * Diplaying fragment view for selected nav drawer list item
     */
    private void displayView(int position) {
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(navMenuTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
        Fragment fragment = null;

        switch (position) {
            case 0:
                fragment = new TabHostFragment();
                break;
            case 1:
                fragment = new RecomendacionesFragment();
                break;
            case 2:
                fragment = new LocalizacionFragment();
                break;
            case 3:
                fragment = new ListaProductosFragment();
                break;
            case 4:
                fragment = new ConfiguracionFragment();
                break;
            case 5:
                fragment = new AyudaSugerenciasFragment();
                break;
            case 6:
                fragment = new AyudaSugerencias();
                break;

            default:

                break;
        }


        if (fragment != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            fragmentManager.beginTransaction()
                    .replace(R.id.frame_container, fragment).commit(); /// here says that replace android.app.Fragment in FragmentTransaction cannot be applied...

            // update selected item and title, then close the drawer
            mDrawerList.setItemChecked(position, true);
            mDrawerList.setSelection(position);
            setTitle(navMenuTitles[position]);
            mDrawerLayout.closeDrawer(mDrawerList);
        } else {
            // error in creating fragment
            Log.e("MainActivity", "Error in creating fragment");
        }
    }


    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().setTitle(mTitle);

    }

    /**
     * When using the ActionBarDrawerToggle, you must call it during
     * onPostCreate() and onConfigurationChanged()...
     */

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggls
        mDrawerToggle.onConfigurationChanged(newConfig);
    }



}

完整的 LogCat 错误是:

  03-04 16:53:05.708    2232-2232/info.androidhive.slidingmenu E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: info.androidhive.slidingmenu, PID: 2232
java.lang.IllegalStateException: No tab known for tag null
        at android.support.v4.app.FragmentTabHost.doTabChanged(FragmentTabHost.java:330)
        at android.support.v4.app.FragmentTabHost.onAttachedToWindow(FragmentTabHost.java:280)
        at android.view.View.dispatchAttachedToWindow(View.java:13406)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2707)
        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2714)
        at android.view.ViewGroup.addViewInner(ViewGroup.java:3919)
        at android.view.ViewGroup.addView(ViewGroup.java:3733)
        at android.view.ViewGroup.addView(ViewGroup.java:3678)
        at android.view.ViewGroup.addView(ViewGroup.java:3654)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:958)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739)
        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1489)
        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:454)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

编辑

@YS 的答案与我所要求的有点不同,但它可能是一个解决方案,但它根本没有正常工作,并且 NavigationDrawer 位于 TabHostFragment 等之下...我不想更改任何布局.

The answer of @Y.S., was kinda different about what I was asking for, but it could be a solution, but it didn't worked fine at all, and the NavigationDrawer is under the TabHostFragment, etc... I don't want to change anything of my layout.

推荐答案

如错误提示

Java:非法状态异常:没有标签为 null 的标签

Java : illegal state exception : no tab known for tag null

您尝试初始化 TabHost,但 TabHost 为空.

you tried to initialise TabHost but TabHost was null.

试试我用来初始化 TabHost 的代码,它工作正常.将代码保存在 onCreateView() 中.当您尝试在 onViewCreated() 中设置您的 FragmentTabHost 时会出现此问题,该调用为时已晚.尝试在onCreateView()中设置,并在返回视图Object之前添加至少一个tab.

Try the code that I have used to initialise the TabHost and it works fine. Keep you code in onCreateView(). This problem occurs when you try to setup your FragmentTabHost in onViewCreated(), which is called too late. Try to set it up in onCreateView(), and add at least one tab before returning the view Object.

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

    // Create FragmentTabHost
    mTabHost = new FragmentTabHost(getActivity());
    // Locate fragment1.xml to create FragmentTabHost
    mTabHost.setup(getActivity(), getChildFragmentManager(), R.layout.fragment1);
    mTabHost.addTab(mTabHost.newTabSpec("groups").setIndicator("",getResources().getDrawable(R.drawable.tab_group_icon)),FragmentTab1.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("",getResources().getDrawable(R.drawable.tab_user_icon)),FragmentTab2.class, null);

    MainActivity.fabButton.setVisibility(View.VISIBLE);
    return mTabHost;
}

布局改为:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1" />

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0" />

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

</LinearLayout>

希望对你有帮助.

相关文章