How to handle back button using view pager?

2020-08-19 05:57发布

问题:

I am having two fragments Frag A and Frag B which are rendered using view pager . If user has swiped from A to B then presses back button(when in B) then user should go to A instead of coming out of view pager . How can we achieve this ?

Adding transaction to backstack does not seem to help .

Thanks

回答1:

You have to override the onKeyDown() method in the Activity.

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        myViewPager.setCurrentItem(0, true);
        return true;
    } else {
       return super.onKeyDown(keyCode, event);
    }
}

This will capture the "back" button press event and send the user to the first item in the ViewPager.

There is also ViewPager#getCurrentItem() which can be used to go back only if the user swiped. An implementation like this:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && myViewPager.getCurrentItem() == 1) {
        myViewPager.setCurrentItem(0, true);
        return true;
    } else {
       return super.onKeyDown(keyCode, event);
    }
}

would send the user back to the previous page only if the user was on the next page. Else, it will register the "back" normally and the user will exit as expected.

You may want the case in which the user goes back to the previous page (assuming you have more than two pages). In which case, you want to implement the ViewPager.OnPageChangeListener() and save the position every time onPageSelected(int position) is called. If you implement them in a stack, then you can pop them off every time the user presses "back". Once the stack is empty, exit the app.

EDIT

As correctly stated in the comments by Jade Byfield, a slightly easier way to do this would be to use onBackPressed() in the Activity. This will only work in API levels 5+.

@Override
public void onBackPressed() {
  if(i_dont_want_to_leave) {
     myViewPager.setCurrentItem(0, true);
  } else {
    super.onBackPressed(); // This will pop the Activity from the stack.
  }
}


回答2:

On the Android Docs page

https://developer.android.com/training/animation/screen-slide.html#viewpager

I found an example of handling ViewPager sliding and there's a method

@Override
public void onBackPressed() {
  if (mPager.getCurrentItem() == 0) {
    super.onBackPressed();
  }
  else {
    mPager.setCurrentItem(mPager.getCurrentItem() - 1);
  }
}

This selects the previous page or exits the active activity.



回答3:

I think a better approach would be to delegate the back key handling to the respective fragments. I have used a CustomFragment which supports a method to handle the back key. All the Fragments will be extending from this CustomFragment.

public abstract class BackKeyHandlingFragment extends Fragment {
    public abstract boolean handleBackKey();
}

Activity can delegate the backKey processing to current Fragment. Fragments can perform required actions in their respective implementation of handleBackKey method. The method can return true to tell activity not to process the back key. To go ahead with default back key action at Activity level, the method can return false.

public void onBackPressed() {
     BackKeyHandlingFragment fragment = (BackKeyHandlingFragment) mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
     // Fragment should return boolean according to app requirements after processing back key
     if (!fragment.handleBackKey()) { 
        super.onBackPressed();
    }
}