竖屏切换横屏时ViewPager中Fragment无法移除问题求助
Hey, I’ve dealt with this exact problem before—orientation changes can be tricky with Fragments because Android automatically saves and restores Fragment instances for you, which leads to those leftover ViewPager Fragments sticking around even after you switch layouts. Let’s walk through the solution step by step.
Why Your Current Code Isn’t Working
When you rotate the screen, Android destroys and recreates your Activity. The FragmentManager automatically keeps track of all Fragments you added earlier (including the ones in your ViewPager). Even though your landscape layout doesn’t have a ViewPager, those old Fragments are still in the FragmentManager, in a "detached" state. When the Activity recreates, the FragmentManager tries to restore their views, which is why onCreateView() is still being called. Your replace calls only affect the new landscape containers—they don’t touch the old ViewPager Fragments.
Step 1: Clean Up Old Fragments First
Before setting up your new layout (whether portrait or landscape), you need to explicitly remove any existing Fragments that might conflict. Add this code right after initializing your ViewModel:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewModel = ViewModelProviders.of(this).get(MainViewModel.class); // Clean up existing Fragments to avoid duplicates/leaks FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction cleanupTransaction = fragmentManager.beginTransaction(); // Remove Fragments tagged for landscape Fragment oldCurrent = fragmentManager.findFragmentByTag("current"); Fragment oldForecast = fragmentManager.findFragmentByTag("forecast"); if (oldCurrent != null) cleanupTransaction.remove(oldCurrent); if (oldForecast != null) cleanupTransaction.remove(oldForecast); // Remove ViewPager Fragments (their tags follow the pattern: "android:switcher:[viewPagerId]:[position]") Fragment viewPagerCurrent = fragmentManager.findFragmentByTag("android:switcher:" + R.id.pager + ":0"); Fragment viewPagerForecast = fragmentManager.findFragmentByTag("android:switcher:" + R.id.pager + ":1"); if (viewPagerCurrent != null) cleanupTransaction.remove(viewPagerCurrent); if (viewPagerForecast != null) cleanupTransaction.remove(viewPagerForecast); // Use commitNow() to execute immediately (avoids async conflicts) cleanupTransaction.commitNow(); // Rest of your orientation logic... int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.weather_layout, new CurrentWeatherFragment(), "current"); fragmentTransaction.replace(R.id.forecast_layout, new ForecastFragment(), "forecast"); fragmentTransaction.commit(); } else { ViewPager viewPager = findViewById(R.id.pager); WeatherPageAdapter weatherPageAdapter = new WeatherPageAdapter(getSupportFragmentManager()); viewPager.setAdapter(weatherPageAdapter); viewPager.addOnPageChangeListener(new WeatherPageChangedListener()); viewPager.setCurrentItem(viewModel.getViewPagerPosition(), false); } }
Step 2: Switch to FragmentStatePagerAdapter (Optional but Recommended)
FragmentPagerAdapter caches Fragments permanently, which is part of why they stick around even after the ViewPager is gone. If you want Fragments to be destroyed when they’re no longer needed (while still saving their state), switch to FragmentStatePagerAdapter:
public class WeatherPageAdapter extends FragmentStatePagerAdapter { private static final int pageNumber = 2; public WeatherPageAdapter(FragmentManager fragmentManager) { // Use BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT to only load the visible Fragment super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @Override public int getCount() { return pageNumber; } @Override public Fragment getItem(int i) { if (i == 0) { return new CurrentWeatherFragment(); } else { return new ForecastFragment(); } } }
Step 3: Save Fragment State (Avoid Data Loss)
Make sure your Fragments save their state so you don’t lose data during rotation. Add this to each Fragment:
@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // Save your data here (e.g., weather objects, user input) outState.putParcelable("weather_data", yourWeatherDataObject); }
Then restore it in onCreateView:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.your_fragment_layout, container, false); if (savedInstanceState != null) { // Restore your data yourWeatherDataObject = savedInstanceState.getParcelable("weather_data"); // Update your UI with the restored data } return view; }
These changes should stop the old ViewPager Fragments from being recreated when you switch to landscape, and ensure your new landscape Fragments work as expected.
内容的提问来源于stack exchange,提问作者Кирилл Волков

