【问题标题】:Use backstack with ViewPager将 backstack 与 ViewPager 一起使用
【发布时间】:2012-09-24 15:24:45
【问题描述】:

我正在使用 ViewPager 在我的 android 应用中实现滑动。但是,我希望在用户使用后退按钮而不是结束活动时显示上一个片段。有没有办法做到这一点? 谢谢 塞巴斯蒂安

【问题讨论】:

    标签: android android-viewpager back-stack


    【解决方案1】:

    我遇到了类似的问题,我就是这样解决的。我有一个带有 6 个片段的 ViewPager,并且想要跟踪页面历史记录并能够使用后退按钮在历史记录中向后导航。我创建了一个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 为假,lastPage 也应更新。
    【解决方案2】:

    在 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);
        }
    }
    

    【讨论】:

      【解决方案3】:

      覆盖 Activity 的功能:

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

      【讨论】:

        【解决方案4】:

        如果您使用的是 Jetpack Navigation 组件,那么您很可能只有一个 Activity 并试图管理 Fragment 中的 backstack。 在这种情况下,OnBackPressedDispatcher 就派上用场了。

        【讨论】:

          【解决方案5】:

          我有同样的问题,我按照这个步骤操作(编辑了我的答案---当然对我有用,试试看

          在 viewpager 中有 3 个片段的主要活动中,我创建了堆栈 并推送和弹出数据。

          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) {
                  }
              });
          }
          

          并在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 {
              }
          }
          

          希望这对我有帮助或给我留言。

          【讨论】:

          • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
          • @JaiprakashSoni 感谢您的建议。我已经编辑了我的答案。希望这可以帮助其他人
          【解决方案6】:

          参考@Piero Nicolli 代码与 kotlin

          这个 anwser 将与 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()

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-09-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多