使用ViewPager时如何使用返回栈

10

我正在使用ViewPager在我的安卓应用程序中实现左右滑动功能。然而,当用户使用返回按钮时,我希望显示先前的碎片而不是结束活动。有没有什么办法可以做到这一点? 谢谢 Sebastian

6个回答

8
我经历了类似的问题,以下是我的解决方法。我有一个ViewPager,其中包含6个片段,并希望跟踪页面历史记录并能够使用返回按钮向后导航。我创建了一个 java.util.Stack<Integer> 对象,将片段编号添加到其中(除非您使用返回按钮,请参见下文),并覆盖 onBackPressed() 方法,使其在我的历史堆栈不为空时弹出最后查看的片段,而不是使用返回堆栈。
当您按下返回键时,要避免将元素推入堆栈中,否则您将在两个片段之间卡住,无法最终退出。
我的代码:
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;
    }
};

你代码中的 currentPage 值从未被设置。 我通过使用一个名为 lastPage 的变量来解决这个问题,并在推入堆栈后将其设置为 onPageSelected 的参数。arg0 是正在导航到的页面,因此我们需要使用该变量来跟踪“上一页”。即使 saveToHistory 为 false,也应更新 lastPage - Trex

7
在Fragment Activity中覆盖下面的方法应该可以解决您的问题。
@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);
    }
}

5

覆盖您的Activity的功能:

public class Activity extends Activity
{
    @Override
    public void onBackPressed()
    {
        // do stuff
        myFragment.onBackPressed();
    }
}

public class Fragment extends Fragment
{

    public void onBackPressed()
    {
        // do stuff
    }
}

2
如果您正在使用Jetpack Navigation组件,那么很可能只有一个activity,并试图在fragment内管理backstack。 在这种情况下,OnBackPressedDispatcher非常有用。

1
我有同样的问题,我按照以下步骤进行操作(编辑了我的答案---肯定对我起作用,试一试)。
在主活动中,有3个片段在viewpager中,我创建了一个堆栈,并推入和弹出数据。
private Stack<Integer> stackkk;
private ViewPager mPager;
private int tabPosition = 0;



    mTabLayout.setupWithViewPager(mPager);
    mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
    mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            tabPosition = tab.getPosition();
            mPager.setCurrentItem(tab.getPosition());

// here i have add the data into the stack in each tab click, as at first it will always be null so i add 0 position

            if (stackkk.empty())
                stackkk.push(0);

            if (stackkk.contains(tabPosition)) {
                stackkk.remove(stackkk.indexOf(tabPosition));
                stackkk.push(tabPosition);
            } else {
                stackkk.push(tabPosition);
            }
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            tabPositionUnselected = tab.getPosition();
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
        }
    });
}

在activity中的onBackPressed方法中,
//OnbackPress i have first taken out the last one as it already and
//selected by poping it out then only set to the pager.
@Override
public void onBackPressed() {
    if (stackkk.size() > 1) {
        stackkk.pop();
        mPager.setCurrentItem(stackkk.lastElement());
    } else {
    }
}

希望这能帮到你,或者给我发消息。

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - Jaiprakash Soni
@JaiprakashSoni 感谢您的建议。我已经编辑了我的答案。希望这可以帮助其他人。 - Ravikant Paudel

0

参考 @Piero Nicolli 的 Kotlin 代码

这个答案的工作方式与 Instagram 导航相同,一旦您访问了相同的选项卡,您就不会再次访问它。

  val pageHistory = Stack<Int>()
  var saveToHistory = false
  var viewPager: ViewPager? = null

如果您正在Fragment中使用ViewPager,则在OnCreate或OnCreateView内部

viewPager?.adapter = viewPagerAdapter

 pageHistory.push(0);
        viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int,
            ) {

            }

            override fun onPageSelected(position: Int) {
                if (saveToHistory) {
                    if (pageHistory.contains(position)) {
                        pageHistory.remove(position)
                        pageHistory.push(position);
                    } else {
                        pageHistory.push(position);
                    }
                }
            }

            override fun onPageScrollStateChanged(state: Int) {
            }
        })
        saveToHistory = true;
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
            // Handle the back button event
            Log.i(TAG, "pageHistory size ${pageHistory.size}")
            if (pageHistory.size > 1) {

                saveToHistory = false;
                pageHistory.pop()
                viewPager?.currentItem = pageHistory.peek()
                saveToHistory = true;

            } else {
                Log.i(TAG, "pageHistory inside 0 size ${pageHistory.size}")

                if(pageHistory.size ==1){
                    pageHistory.pop()
                }
                if (viewPager?.currentItem == 0){
                    requireActivity().finish()
                }else{
                    viewPager?.currentItem = 0
                }
            }

        }

由于我正在使用Fragment,因此可以使用onBackPressedDispatcher回调函数来处理返回按钮。 如果您在Activity中使用viewpager,则将代码从onBackPressedDispatcher()复制到onBackPressed()中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接