问题描述
几天前,我在 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.
我到处搜索,在 SO、code.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>
希望对你有帮助.