Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use backstack with ViewPager

I am using a ViewPager to implement swiping in my android app. However, I would like the previous fragment to be shown when the user uses the back button instead of ending the activity. Is there any way to do that? Thanks Sebastian

like image 985
Sebastian Avatar asked Oct 03 '12 16:10

Sebastian


3 Answers

If you are using the Jetpack Navigation component, chances are you have a single activity and are trying to manage the backstack inside a fragments. In which case the OnBackPressedDispatcher comes handy.

like image 175
ancyr Avatar answered Oct 17 '22 04:10

ancyr


I had a similar problem, this is how I solved it. I had a ViewPager with 6 fragments and wanted to keep track of the page history and to be able to use the back button to navigate backwards in the history. I create a java.util.Stack<Integer> object, add fragment numbers to it (except when you use the back button, see below), and override onBackPressed() to make it pop the last viewed fragment instead of using the back stack, when my history stack is not empty.

You want to avoid pushing elements on the Stack when you press the back button, otherwise you will get stuck between two fragments if you keep using the back button, instead of eventually exiting.

My code:

MyAdapter mAdapter;
ViewPager mPager;
Stack<Integer> pageHistory;
int currentPage;
boolean saveToHistory;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mAdapter = new MyAdapter(getSupportFragmentManager());
    mPager = (ViewPager)findViewById(R.id.container);
    mPager.setAdapter(mAdapter);
    mPager.setOffscreenPageLimit(5);

    pageHistory = new Stack<Integer>();
    mPager.setOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int arg0) {
            if(saveToHistory)
                pageHistory.push(Integer.valueOf(currentPage));
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
    saveToHistory = true;
}

@Override
public void onBackPressed() {
    if(pageHistory.empty())
        super.onBackPressed();
    else {
        saveToHistory = false;
        mPager.setCurrentItem(pageHistory.pop().intValue());
        saveToHistory = true;
    }
};
like image 42
Piero Nicolli Avatar answered Oct 17 '22 04:10

Piero Nicolli


Overriding below method in Fragment Activity should solve your issue.

@Override
public void onBackPressed() {
    if (mViewPager.getCurrentItem() == 0) {
        // If the user is currently looking at the first step, allow the system to handle the
        // Back button. This calls finish() on this activity and pops the back stack.
        super.onBackPressed();
    } else {
        // Otherwise, select the previous step.
        mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1);
    }
}
like image 45
refactor Avatar answered Oct 17 '22 03:10

refactor