You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

底部导航重复点击后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 parent Packages Fragment'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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:19:48