ViewPager setCurrentItem Slide

10

我有一个包含ViewPager的Activity,ViewPager中的第一个Fragment包含ListView,当我点击任何项目时,它会用所选的Fragment替换此Fragment, 我使用setCurrentItem(selectedItem, true)//平滑滚动,但ViewPager在选择的Fragment之前滑过所有Fragment。 我希望它仅滑到所选Fragment而不是所有Fragment。 我尝试使用PageTransfrom.transformPage来实现这一点

@Override
public void transformPage(View page, float position) {
    int currentItem = viewPager.getCurrentItem();
    if (currentItem != selectedItem)
        page.setVisibility(View.GONE);
}

但是没有好运。


你是否在使用自定义的 ViewPagerAdapter - Droidekas
6个回答

4
一种可能的解决方案是修改PagerAdapter,使其始终返回第二项。当从第一页中点击任何项时,首先要更改PagerAdapter的getItem(int position)方法实现(如果您的PagerAdapter实现在同一个类文件中,则很容易实现),以在position == 2时返回您想要的页面,然后调用setCurrentItem(2, true)。这可以直接滑动到所选页面。您还需要更改getCount(),将计数限制为只有2个,否则下一页可能不是预期的页面。但此方法会忽略其他页面。用户只能向后滚动到第一页,然后导航到另一页。如果您想保持手动滚动(而非点击)的自然顺序,可以一旦停止滚动(通过单击),就将getItem(int position)还原为默认实现,并通过调用setCurrentItem(position, false)(此次立即而不是平稳地)重新加载已停止的当前页面到自然顺序,然后用户可以手动前后滚动。

1
这是我解决它的最接近的想法。 - Ma7moud El-Naggar

0
一般来说,正如许多人已经说过的那样,你不应该使用ViewPager,因为它绝对不是为其他目的而设计的。
我认为最简单的方法是只使用简单的片段切换,例如:
yourListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                switch (position) {
                    case 0:
                        getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right)
                                .replace(R.id.content, MyFirstFragment.newInsance()).commit();
                        break;
                    case 1:
                        getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right)
                                .replace(R.id.content, MySecondFragment.newInsance()).commit();
                        /etc.
                }
            }
        });

这样你就可以完全控制它,还可以为每个片段的出现设置适当的动画。

希望你明白我的意思。


0
我是这样解决这个问题的: 我有一个ViewPager(vp1),包含两个Fragment,第一个包含项目的ListView,第二个Fragment包含另一个ViewPager(vp2) 我滑动到所选项目,而不是滑过所有先前的项目,就像这样 当用户在Listview上单击项目时
vp2.setCurrentItem(selectedItemIndex,false);
vp1.setCurrentItem(1,true);

先在第二个ViewPager上设置当前项目而不需要滑动,然后滑动第一个ViewPager,就这样。


0
如果你希望幻灯片可以从一个项目向另一个项目滑动,你必须使不仅被选中的项目可见,还要保证之前被选中的项目也可见。在调用setCurrentItem(selectedItem,true)之后,在transformPage里所有对viewPager.getCurrentItem()的调用都会返回之前设置的值,而不是通过平滑滚动实际改变的值。我认为你可以使用以下方式来完成这个需求:
int prevSelFrag = 0, currentSelFrag = 0; //member variables

@Override
protected void onCreate(Bundle savedInstanceState) {
    pager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(int pos) {
            prevSelFrag = currentSelFrag;
            currentSelFrag = pos;
        }

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

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
    pager.setPageTransformer(false, new PageTransformer() {
        @Override
        public void transformPage(View page, float relativePosition) {
            float transDiff = prevSelFrag - currentSelFrag;
            if (transDiff > 1.0f || transDiff < -1.0f) {
                boolean transIsToRight = transDiff < 0.0f;
                if (transIsToRight && relativePosition < -1) {
                    page.setVisibility(View.GONE);
                } else if (relativePosition > 1) { //trans is to left
                    page.setVisibility(View.GONE);
                }else{
                    page.setVisibility(View.VISIBLE);
                }
            }else{
                page.setVisibility(View.VISIBLE);
            }
        }
    });
}

relativePosition是相对于setCurrentItem设置的页面位置,因此给定的View page在动画中必须到达该位置(但不是在实际的分页器状态中)。例如,如果您在页面0上并调用transformPage中的setCurrentItem(2,true),则可能会收到以下结果:

  • 相对位置为-2的页面1中的当前视图
  • 相对位置为-1的页面0中的当前视图
  • 相对位置为0的页面2中的当前视图

当然这些值之间会变化以产生过渡效果。ViewPager smoothScroll对我无效,我不得不使用此解决方案来修复它 -> https://dev59.com/xmct5IYBdhLWcg3wmOng#14776244


0

所以,如果我理解你的意思正确的话,你想要一个平滑的滚动到选定的片段,但只从上一个片段开始。对吗?

当你将true传递给setCurrentItem时,它会从当前选择的位置进行平滑滚动。这是无法改变的。因此,解决您的问题的方法是进行两步设置。

首先使用setCurrentItem(selectedItem-1, false)将其设置为前一个项目。一旦该转换完成,调用setCurrentItem(selectedItem, true)。

我自己没有做过这个,但我预见到了一些复杂情况和特殊情况。

如果您将一个setCurrentItem调用放在另一个后面,它可能不起作用。您可能需要监听第一页更改(使用OnPageChangeListener)来执行第二个setCurrentItem调用。

还有当所选项目是第一个项目时的越界问题。

希望这可以帮助到您。


setCurrentItem(selectedIndex-1,false)会显示selectedIndex-1的项目,因此它不适合作为用户体验。 - Ma7moud El-Naggar
在selectedItem-1完成后,你才会对selectedItem进行平滑的过渡效果,这正是你想要的,对吗? - shalafi

0

ViewPager 不是你想要实现的正确工具。如果你使用 ViewPager,将 Fragments 添加为页面,并从第 0 页滚动到第 3 页,它肯定会从 第 0 页 -> 第 1 页 -> 第 2 页 -> 第 3 页 滚动。一般来说,它会一步一步地进行,其中一步对应着移动到下一页。

你要寻找的是 后代导航

在你的情况下,你可以保留所有的片段实现。只需将包含 ListViewFragment 托管到一个活动中,当用户在其中选择一个项目时,使用 滑入转换 添加相应的 Fragment

祝你好运。


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