Android ViewPager - 此设计的平滑过渡

Posted

技术标签:

【中文标题】Android ViewPager - 此设计的平滑过渡【英文标题】:Android ViewPager - Smooth Transition for this Design 【发布时间】:2015-11-29 19:53:52 【问题描述】:

我真的无法计算出为以下设计进行平滑过渡的数学方法。任何帮助将不胜感激:)。

在过渡期间,页面会上下跳动,但我希望它们变得平滑。

设计

过渡

相关ViewPage代码:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
    PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(pagerAdapter);
    viewPager.setOffscreenPageLimit(3);
    viewPager.setPageMargin(100);
    viewPager.setPageTransformer(false, new ViewPager.PageTransformer() 
        @Override
        public void transformPage(View page, float position) 
            int pageWidth = viewPager.getMeasuredWidth() - viewPager.getPaddingLeft() - viewPager.getPaddingRight();
            int pageHeight = viewPager.getHeight();
            int paddingLeft = viewPager.getPaddingLeft();
            float transformPos = (float) (page.getLeft() - (viewPager.getScrollX() + paddingLeft)) / pageWidth;

            final float normalizedposition = Math.abs(Math.abs(transformPos) - 1);
            page.setAlpha(normalizedposition + 0.5f);

            if (transformPos < -1)  // [-Infinity,-1)
                // This page is way off-screen to the left.
                page.setTranslationY(0);
             else if (transformPos <= 1)  // [-1,1]
                page.setTranslationY(-pageHeight / 10);

             else  // (1,+Infinity]
                // This page is way off-screen to the right.
                page.setTranslationY(0);
            


        
    );


注意:'transformPos' 用于解决此错误 - https://code.google.com/p/android/issues/detail?id=64046

我的 ViewPager

<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_
    android:layout_
    android:layout_centerInParent="true"
    android:clipToPadding="false"
    android:paddingLeft="80dp"
    android:paddingRight="80dp"/>

完整来源 - https://github.com/krishnaraj/ViewPagerSample

【问题讨论】:

有什么问题? @MarkGilchrist 当您向左/向右滑动时,过渡不平滑。 也许你应该将你的示例项目上传到 github,这样人们会更容易检查它有多不顺利 @DerekFung 添加了指向 Github 存储库和动画图像的链接。 【参考方案1】:

试试这个

    viewPager.setPageTransformer(false, new ViewPager.PageTransformer() 
        @Override
        public void transformPage(View page, float position) 
            int pageWidth = viewPager.getMeasuredWidth() - viewPager.getPaddingLeft() - viewPager.getPaddingRight();
            int pageHeight = viewPager.getHeight();
            int paddingLeft = viewPager.getPaddingLeft();
            float transformPos = (float) (page.getLeft() - (viewPager.getScrollX() + paddingLeft)) / pageWidth;

            final float normalizedposition = Math.abs(Math.abs(transformPos) - 1);
            page.setAlpha(normalizedposition + 0.5f);

            int max = -pageHeight / 10;

            if (transformPos < -1)  // [-Infinity,-1)
                // This page is way off-screen to the left.
                page.setTranslationY(0);
             else if (transformPos <= 1)  // [-1,1]
                page.setTranslationY(max * (1-Math.abs(transformPos)));

             else  // (1,+Infinity]
                // This page is way off-screen to the right.
                page.setTranslationY(0);
            


        
    );

【讨论】:

完美工作! blpinsk 的答案也很有效,但由于代码较短而接受了这个:)【参考方案2】:

将您的 if 更改为:

float upTranslation = -pageHeight / 10f;
if (transformPos < -1) // [-Infinity,-1)
    page.setTranslationY(0);
 else if (transformPos < 0)  // [-1,0)
    float translationY = upTranslation * (transformPos + 1f);
    page.setTranslationY(translationY);
 else if (transformPos == 0)  // 0
    page.setTranslationY(upTranslation);
 else if (transformPos <= 1)  // (0,1]
    float translationY = upTranslation * (1f - transformPos);
    page.setTranslationY(translationY);
 else  // (1,+Infinity]
    page.setTranslationY(0);

【讨论】:

效果很好,但在这与 Derek Fung 的答案之间的最终过渡中找不到任何明显的差异。 它的工作原理完全相同(我的代码可能更容易解释)。老实说,自从我开始写答案以来,我没有查看是否有任何其他正确答案就发布了答案。但正如我所见,Derek Fung 在我面前发布了他的答案,所以他值得称赞 :)。干杯!【参考方案3】:

如果你真的不需要pageTransformer,使用下面的代码

    viewPager.setPageTransformer(false, new ViewPager.PageTransformer() 
    @Override
    public void transformPage(View page, float position) 
        if(position==1)

            int pageWidth = viewPager.getMeasuredWidth() - viewPager.getPaddingLeft() - viewPager.getPaddingRight();
            int pageHeight = viewPager.getHeight();
            int paddingLeft = viewPager.getPaddingLeft();
            float transformPos = (float) (page.getLeft() - (viewPager.getScrollX() + paddingLeft)) / pageWidth;

            final float normalizedposition = Math.abs(Math.abs(transformPos) - 1);
            page.setAlpha(normalizedposition + 0.5f);

            if (transformPos < -1)  // [-Infinity,-1)
                // This page is way off-screen to the left.
                page.setTranslationY(0);
             else if (transformPos <= 1)  // [-1,1]
                page.setTranslationY(-pageHeight / 10);

             else  // (1,+Infinity]
                // This page is way off-screen to the right.
                page.setTranslationY(0);
            
        
    
);

然后再试一次...

【讨论】:

但是我需要边距在标签之间留出空间。 好吧,好像有什么误会。我实际上需要中心选项卡高于预览选项卡(请参阅上面更新的静态图像)。 好的,然后在上面的方法中你有位置,只需放入 if(position==1) 并将该方法中的所有代码移到其中,检查更新的答案

以上是关于Android ViewPager - 此设计的平滑过渡的主要内容,如果未能解决你的问题,请参考以下文章

使用ViewPager2+TabLayout设计主布局

使用ViewPager2+TabLayout设计主布局

Android UI设计与开发使用ViewPager实现欢迎引导页面

Android:Viewpager 和 FragmentStatePageAdapter

如何使用 viewpager(android) 创建动态选项卡?

Android ViewPager + Fragment 懒加载数据 可操作控件版