Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if fragment restart is due to screen rotation or Viewpager swipe?

I have an Activity with ViewPager. the ViewPager have a lot of pages, Just like a book. Each fragment has RecyclerViews with a lot of content. The following is my use case

1 - When I swipe page, RecyclerView must start from the beginning of the list. 2. If I rotate my device, It should read from exact last position of where I left before rotation.

If I don't use any logic, 2nd scenario works perfectly. ie, rotation. But not the first scenario.

If I do some logic like below. Helps to achieve first scenario, But not the second scenario.

  @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    if (savedInstanceState==null) {
        mIsFirstTime = true;
    }
}

@Override
public void onResume() {
    super.onResume();
    try {
        getActivity().invalidateOptionsMenu();
            if (!mIsFirstTime) {
                mListView.scrollToPosition(0);                
            }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

So My question is

How can I determine a fragment restart is due to screen rotation or Viewpager swipe?

I already tried onConfigurationChanged(Configuration newConfig) . But it doesn't help me. Could you please help me

like image 572
Vinayak B Avatar asked Jan 29 '18 05:01

Vinayak B


People also ask

What happens to fragment when activity is rotated?

Fragments — Scenario 3: Activity with retained Fragment is rotated. The fragment is not destroyed nor created after the rotation because the same fragment instance is used after the activity is recreated. The state bundle is still available in onActivityCreated .

How do you know when a fragment becomes visible?

fragment:fragment:1.1. 0 you can just use onPause and onResume callbacks to determine which fragment is currently visible for the user. onResume callback is called when fragment became visible and onPause when it stops to be visible.

How do you not start all fragments together on Viewpager when Fragment A is selected?

Using an OnPageChangeListener in your View Pager, you can detect which fragment is currently shown in the View Pager. You'll then need to check which fragment is shown and then call a method on that fragment's class to start any sounds for example that you don't want to start until the fragment is the fragment in view.


2 Answers

From a comment of OP:

My question is how I know that onSaveInstanceState() is called due to screen orientation change and not fragment restart

You can do that via Activity#isChangingConfigurations() API.


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        if (isChangingConfigurations()) {
            // this callback is executed as a result of a configuration change (e.g. orientation change)
        } else {
            // no configuration change happens (e.g. a click on a home button would end up here)
        }
    }

Now you can save a boolean value into Bundle outState and appropriate setup UI after recreation:


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("isConfigurationChange", isChangingConfigurations());
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // initialization logics here

        if (savedInstanceState != null) {
            boolean isConfigurationChange = savedInstanceState.getBoolean("isConfigurationChange");

            // if `onCreate` is called as a result of configuration change
            if (isConfigurationChange) {
                // view hierarchy is not yet laid out, have to post an action 
                listView.post(new Runnable() {
                    @Override
                    public void run() {
                        // we are guaranteed, that `listView` is already laid out
                        listView.scrollToPosition(0);
                    }
                });
            }
        }
    }

Note, that performing boolean value checking logics inside onResume() is a bug (pressing home button and navigating back to the app would result in scrolling to the top again, which is not desired). Instead onCreate() should be chosen as a correct callback.

like image 134
azizbekian Avatar answered Oct 27 '22 20:10

azizbekian


I think you can declare a variable and check the status to true on swipe action.

viewPager.addOnPageChangeListener(new OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

public void onPageSelected(int position) {
// here assign the variable to true;
// This method will get called only after a swipe action is invoked on 
//viewpager.  
 }});

Inside your fragment check whether the variable status is true, if so it's not getting generated from orientation, then reset the variable to false.

Happy coding :)

like image 1
Manoj Perumarath Avatar answered Oct 27 '22 18:10

Manoj Perumarath