1

My activity should handle portrait and landscape layouts in different ways: if layout is portrait, then in should use ViewPager with two fragments. If layout is landscape, then it should just divide screen on two parts and locate two fragments there. The problem is that when I switch from portrait to landscape, viewpager's fragments are not removed and onCreateView() is called for them.

Calling removing fragments with FragmentTransaction does nothing.

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        int orientation = getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            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);
        }
    }

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.example.android.myapplication.ui.fragments.CurrentWeatherFragment;
import com.example.android.myapplication.ui.fragments.ForecastFragment;

public class WeatherPageAdapter extends FragmentPagerAdapter {
    private static final int pageNumber = 2;

    public WeatherPageAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @Override
    public int getCount() {
        return pageNumber;
    }

    @Override
    public Fragment getItem(int i) {
        if (i == 0) {
            return new CurrentWeatherFragment();
        }
        else {
            return new ForecastFragment();
        }
    }
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:rowCount="7"
    android:columnCount="2"
    tools:context=".ui.activities.MainActivity">

    <androidx.viewpager.widget.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:rowCount="7"
    android:columnCount="2"
    tools:context=".ui.activities.MainActivity"
    android:orientation="horizontal"
    android:baselineAligned="false">

    <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/weather_layout">
    </FrameLayout>

    <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/forecast_layout">
    </FrameLayout>

</LinearLayout>

1 Answers1

0

In your earlier code, Do the following modification:

private ViewPager viewPager;
private WeatherPageAdapter weatherPageAdapter;


protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        changeViewAsPerOrientation(getResources().getConfiguration().orientation);
    }

private void changeViewAsPerOrientation(Configuration newConfig) {
      for (Fragment fragment : getSupportFragmentManager().getFragments()) {
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        }
      if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        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 {
         if(viewPager == null || weatherPageAdapter == null) {
          viewPager = findViewById(R.id.pager);
          weatherPageAdapter = new  WeatherPageAdapter(getSupportFragmentManager());
          viewPager.addOnPageChangeListener(new WeatherPageChangedListener());
        } else {
          adapter.notifyDataSetChanged();
        }

        viewPager.setCurrentItem(viewModel.getViewPagerPosition(), false);
      }
    }

@Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    changeViewAsPerOrientation(newConfig);
  }
Deˣ
  • 4,191
  • 15
  • 24
  • Where should I call that two rows? – Кирилл Волков Jun 19 '19 at 09:46
  • then I should add ViewPager in both, portrait and landscape, xml layouts? – Кирилл Волков Jun 19 '19 at 10:28
  • Sorry. But if i call ```viewPager.addOnPageChangeListener(new WeatherPageChangedListener());``` in landscape mode, then I get ```NullPointerException``` because I do not have it in landscape XML layout. Thus I ask about adding it there. – Кирилл Волков Jun 19 '19 at 10:54
  • Oh! Sorry for that. I thought you have a single layout. I have now modified the code. please try again. – Deˣ Jun 19 '19 at 11:36
  • This ViewPagerAdapter will break after process death (see https://stackoverflow.com/questions/49046773/singleton-object-becomes-null-after-app-is-resumed/49107399#49107399), the fragments you provide from outside will NEVER be used, and the fragments in `pageList` and `forecastFragment` and `currentWeatherFragment` will NOT be the same instance as what is on the screen. Please don't get people to use this, because it is wrong and it will eventually break (see https://stackoverflow.com/questions/55753099/app-crash-after-activity-has-been-killed-in-background/55754360#55754360) – EpicPandaForce Jun 19 '19 at 11:54
  • @EpicPandaForce Thank you for your info. I have updated the answer. Let me know if it's the correct way. – Deˣ Jun 19 '19 at 12:09
  • I guess that would technically work, but it will lose view state across orientation changes. You would also need to do some sort of trickery, similar to https://github.com/Zhuinden/simple-stack/blob/8edd0c80e2887c429fc2dede5f3c5607a7e2a47d/simple-stack-flow-masterdetail-fragments/src/main/java/com/example/stackmasterdetailfrag/MasterDetailFragmentStateChanger.java#L114-L117 . – EpicPandaForce Jun 19 '19 at 12:36
  • @EpicPandaForce Yes, you are right. It won't maintain the view state. But then I might have to write the whole application code here. – Deˣ Jun 19 '19 at 12:41
  • 1
    Fragments are pain XD – EpicPandaForce Jun 19 '19 at 12:45
  • Technically that downvote went for the `ViewPagerAdapter(List – EpicPandaForce Jun 19 '19 at 12:48
  • @EpicPandaForce Thanks again for informing about it. I was totally unaware of that. Кирилл Волков Try this https://developer.android.com/training/basics/fragments/fragment-ui It may help. – Deˣ Jun 19 '19 at 12:53
  • Code doesn't work(( FragmentTransactipn doesn't remove view pager's fragments – Кирилл Волков Jun 19 '19 at 13:17