底部导航重复点击后TabHost内容不显示问题求助
Hey there, let's dig into why your TabHost stops showing content when you re-click the bottom navigation item. From looking at your code, I spot a couple of key issues that are causing this behavior, and here's how to fix them step by step:
1. Fix Fragment Reuse Logic in Home Activity
Right now, you're creating a new Packages Fragment instance every time the navigation item is clicked. This not only wastes resources but also resets the TabHost state unnecessarily. Instead, we'll cache and reuse existing Fragment instances with hide/show instead of replace:
public class Home extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { // Cache your Fragment instance to preserve state private Packages mPackagesFragment; private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // Hide all active fragments first hideAllFragments(transaction); switch (item.getItemId()) { case R.id.ic_public: setTitle("Internet"); if (mPackagesFragment == null) { mPackagesFragment = new Packages(); transaction.add(R.id.content, mPackagesFragment, "FragmentName"); } else { transaction.show(mPackagesFragment); } transaction.commit(); return true; // Add logic for other navigation items here } return false; } }; // Helper method to hide all cached fragments private void hideAllFragments(FragmentTransaction transaction) { if (mPackagesFragment != null) { transaction.hide(mPackagesFragment); } // Add hiding logic for other fragments if you have them } }
2. Correct FragmentManager Usage in Packages Fragment
Your current code uses the Activity's FragmentManager to manage child fragments inside Packages, which breaks the lifecycle synchronization between parent and child fragments. Instead, use the Fragment's own getChildFragmentManager():
public class Packages extends Fragment { View view; private TabHost mPackagesTabHost; private ViewPager mPackagesViewPager; public Packages() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, android.os.Bundle savedInstanceState) { if (view == null) { view = inflater.inflate(R.layout.fragment_packages, container, false); mPackagesTabHost = view.findViewById(R.id.packagestab); // Initialize FragmentTabHost with the correct FragmentManager and container ID mPackagesTabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent); mPackagesViewPager = view.findViewById(R.id.packagespager); mPackagesViewPager.setOffscreenPageLimit(2); // Pass getChildFragmentManager() instead of Activity's FragmentManager PackagesTabsAdapter tabsAdapter = new PackagesTabsAdapter(getChildFragmentManager(), getActivity(), mPackagesTabHost, mPackagesViewPager); tabsAdapter.addTab(mPackagesTabHost.newTabSpec("one").setIndicator("50 MB"), TurbooneFragment.class, null); tabsAdapter.addTab(mPackagesTabHost.newTabSpec("two").setIndicator("300 MB"), TurbotwoFragment.class, null); } return view; } }
3. Update PackagesTabsAdapter to Use the Correct FragmentManager
Modify the adapter's constructor to accept a FragmentManager parameter (instead of fetching it from the Activity) to align with the parent Fragment's lifecycle:
public class PackagesTabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener { private final Context mContext; private final TabHost mTabHost; private final ViewPager mViewPager; private final ArrayList<TabInfo> mTabs = new ArrayList<>(); static final class TabInfo { private final Class<?> clss; private final Bundle args; TabInfo(Class<?> _class, Bundle _args) { clss = _class; args = _args; } } static class DummyTabFactory implements TabHost.TabContentFactory { private final Context mContext; DummyTabFactory(Context context) { mContext = context; } public View createTabContent(String tag) { View v = new View(mContext); v.setMinimumWidth(0); v.setMinimumHeight(0); return v; } } // Updated constructor to accept FragmentManager public PackagesTabsAdapter(FragmentManager fragmentManager, Context context, TabHost tabHost, ViewPager pager) { super(fragmentManager); mContext = context; mTabHost = tabHost; mViewPager = pager; mTabHost.setOnTabChangedListener(this); mViewPager.setAdapter(this); mViewPager.setOnPageChangeListener(this); } public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { tabSpec.setContent(new DummyTabFactory(mContext)); String tag = tabSpec.getTag(); TabInfo info = new TabInfo(clss, args); mTabs.add(info); mTabHost.addTab(tabSpec); notifyDataSetChanged(); } @Override public int getCount() { return mTabs.size(); } @Override public Fragment getItem(int position) { TabInfo info = mTabs.get(position); Log.d("HelpFragment", "Creating Fragment " + position); return Fragment.instantiate(mContext, info.clss.getName(), info.args); } // Complete the onTabChanged method (your original code was truncated) @Override public void onTabChanged(String tabId) { int position = mTabHost.getCurrentTab(); mViewPager.setCurrentItem(position); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} @Override public void onPageSelected(int position) { mTabHost.setCurrentTab(position); } @Override public void onPageScrollStateChanged(int state) {} }
Why This Works
- Fragment Reuse: Caching fragments preserves the TabHost's state between navigation clicks, so you don't have to reinitialize everything from scratch.
- getChildFragmentManager(): This ensures child fragments (like
TurbooneFragment) are tied to the parentPackagesFragment's lifecycle, preventing state loss or display issues when the parent is re-shown. - Proper FragmentTabHost Setup: The
setup()method now knows exactly how to manage child fragments using the correct container and FragmentManager.
内容的提问来源于stack exchange,提问作者Cavad

