【问题标题】:Android : Implementation of two way Endless ViewpagerAndroid:两种方式Endless Viewpager的实现
【发布时间】:2016-03-29 05:16:12
【问题描述】:

我想要什么:

我一直在尝试在 Android 中实现 两个方向的 Endless viewpager从左到右 & 从右到左

我做了什么:

我已经实现了无尽的viewpager适配器,它适用于从右到左的方向,我已经通过viewPager.setCurrentItem(Integer.MAX_VALUE/2);设置了当前项目位置。

参考:

帮助将不胜感激。

【问题讨论】:

标签: android android-viewpager adapter infinite-loop two-way


【解决方案1】:

尝试检查下面的FragmentPagerAdapter 以获得无尽的viewpager适配器:

public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public int getCount() {
    return Integer.MAX_VALUE;
}

@Override
public Fragment getItem(int position) {
    return getFragmentBasedOnPosition(position);
}

private Fragment getFragmentBasedOnPosition(int position) {
    int fragmentPos = position % 3; // Assuming you have 3 fragments
    switch(fragmentPos) {
        case 0:
        return Fragment1.newInstance();
        case 1:
        return Fragment2.newInstance();
        case 2:
        return Fragment3.newInstance();
    }
 }
}

我找到了解决方案here

希望对你有帮助。

【讨论】:

  • 感谢您的支持,但正如我所说,我想要两个定向适配器,这意味着如果我在第 0 个位置并且我确实从右向左滑动,那么它应该将 0 移动到 viewpager 的最后一项,我通过stackoverflow.com/questions/7766630/… 实现了我的目标,我将当前位置设置为 Integer.MAX_VALUE/2,但仍在寻找类似 Playstore 应用的东西。
  • @HirenPatel 这应该确实可以,但是他忘了说viewPager应该从中间开始,这样才不会让你那么容易走到最右边。跨度>
  • 如果我不知道 Viewpager 上添加的片段数量怎么办
【解决方案2】:

我已经制定了自己的解决方案。我创建了一个ViewPager,它支持无限循环效果,智能自动滚动,兼容任何指标,使用方便。它特别将其用作带有简单项目页面的应用程序的横幅。

我的自定义 ViewPager 可以:

  • 即插即用,简单易用
  • 无限循环项目
  • 自动滚动项目,允许配置,活动/片段恢复/暂停时自动恢复/暂停
  • 如果只有 1 个项目,则不会滚动或循环
  • 兼容多种指标

Github 链接:https://github.com/kenilt/LoopingViewPager

希望对你有帮助!

【讨论】:

    【解决方案3】:

    ViewPager2 实现这一目标的一个简单方法是使用 3 个基本理念:

    1. 将数据模型集合的第一项和最后一项分别添加到同一集合的末尾和开头。例如。 listOf(1, 2, 3, 4, 5) 应该变成 listOf(5, 1, 2, 3, 4, 5, 1)
    2. 设置寻呼机时,将其设置为从索引 1 开始。
    3. 当用户滚动到索引 0 时,让寻呼机立即滚动到倒数第二个索引。当用户滚动到最后一个索引时,让寻呼机立即滚动到索引 1。

    一些示例代码如下:

    1.

    private fun <T> List<T>.prepareForTwoWayPaging(): List<T> {
        val first = first()
        val last = last()
        return toMutableList().apply {
            add(0, last)
            add(first)
        }
    }
    
    pager.setCurrentItem(1, false)
    
    pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
        override fun onPageScrolled(
            position: Int,
            positionOffset: Float,
            positionOffsetPixels: Int
        ) {
            // We're only interested when the pager offset is exactly centered. This
            // will help create a convincing illusion of two-way paging.
            if (positionOffsetPixels != 0) {
                return
            }
            when (position) {
                0 -> pager.setCurrentItem(adapter.itemCount - 2, false)
                adapter.itemCount - 1 -> pager.setCurrentItem(1, false)
            }
        }
    })
    

    警告:此代码不会协调任何 TabLayout 或空数据模型集合。

    【讨论】:

      【解决方案4】:

      建议的解决方案是正确的,但要获得结果,您需要将 viewpager 的初始值设置为 Integer.MAX_VALUE/2。

      无论如何,我不太喜欢这种解决方案,将 getCount 设置为返回 Integer.MAX_VALUE 会对应用程序性能产生巨大影响。

      为了避免这个问题,我想出了一个解决方案:

      onPageScrollStateChanged 监听器

      我只是重新排序片段列表,更新 viewPager 并移动到没有动画的新页面,结果是双向循环:

      mainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
      {
        Boolean first = false;
        Boolean last = false;
      
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
        {}
      
        @Override
        public void onPageSelected(int position)
        {
          if (position == 0)
          {
            first = true;
            last = false;
          }
          else if (position == mainFragmentList.size() -1)
          {
            first = false;
            last = true;
          }
          else
          {
            first = false;
            last = false;
          }
        }
      
        @Override
        public void onPageScrollStateChanged(int state)
        {
          if (first && state == ViewPager.SCROLL_STATE_IDLE)
          {
            // Jump without animation
            Fragment fragment = mainFragmentList.get(mainFragmentList.size() -1);
            mainFragmentList.remove(mainFragmentList.size() -1 );
            mainFragmentList.add(0,fragment);
            mainPagerAdapter.setData(mainFragmentList);
            mainPagerAdapter.notifyDataSetChanged();
            Log.e(TAG,mainFragmentList.toString());
            mainViewPager.setCurrentItem(1,false);
          }
          if(last && state == ViewPager.SCROLL_STATE_IDLE)
          {
            // Jump without animation
            Fragment fragment = mainFragmentList.get(0);
            mainFragmentList.remove(0);
            mainFragmentList.add(fragment);
            mainPagerAdapter.setData(mainFragmentList);
            mainPagerAdapter.notifyDataSetChanged();
            Log.e(TAG,mainFragmentList.toString());
            mainViewPager.setCurrentItem(mainFragmentList.size()-2,false);
          }
        }
      });
      

      这就是这里发生的事情: 在这个例子中,我们有 4 个片段 A-B-C-D 如果用户在片段 A(第一个)上,则新列表将变为:D-A-B-C [删除最后一个并作为第一个推送] 我更新 ViewPager 并再次移动(没有动画)到片段 A 所以索引 1。 现在用户可以继续向左滚动,会找到片段D。

      与最后一个片段相同: 从 A-B-C-D 重新开始 如果用户在片段 D(最后一个)上,则新列表将变为:B-C-D-A [删除第一个并推最后一个] 我更新 ViewPager 并再次移动(没有动画)到片段 D,以便索引 mainFragmentList.size()-2。 现在用户可以继续向右滚动,将找到片段 A。

      记得实现 FragmentStatePagerAdapter 而不是 FragmentPagerAdapter

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-05
        • 2018-02-08
        相关资源
        最近更新 更多