ViewPager 展示屏幕上的下一个和前一个项目预览。

40

我希望在屏幕中显示viewpager的前一个和后一个页面预览。 前一个和后一个页面深入屏幕显示,并使用深入动画滑动下一个页面。

您可以查看这张图片

我应该怎么做?

输入图像描述


1
请尝试访问以下链接:https://github.com/mrleolink/SimpleInfiniteCarousel - Hasnain
你完美地解决了这个问题吗?在我的情况下,低规格的手机可以完美地工作,但高规格的手机却不能正常工作。 - Md Tariqul Islam
简答 https://dev59.com/Ymkw5IYBdhLWcg3wJXQh#73397935 - Nikunj Paradva
5个回答

23

终于,我做到了 :) 我修改了这个答案 Android - Carousel like widget which displays a portion of the left and right elements

你可以查看这段代码。

//pager settings
          pager.setClipToPadding(false);
          pager.setPageMargin(24);
          pager.setPadding(48, 8, 48, 8);
          pager.setOffscreenPageLimit(3);
          pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

             @Override
             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                Log.i("", "onPageScrolled: " + position);

                CampaignPagerFragment sampleFragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(position);


                float scale = 1 - (positionOffset * RATIO_SCALE);

                // Just a shortcut to findViewById(R.id.image).setScale(scale);
                sampleFragment.scaleImage(scale);


                if (position + 1 < pager.getAdapter().getCount()) {
                   sampleFragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(position + 1);
                   scale = positionOffset * RATIO_SCALE + (1 - RATIO_SCALE);
                   sampleFragment.scaleImage(scale);
                }
             }

             @Override
             public void onPageSelected(int position) {
                Log.i("", "onPageSelected: " + position);
             }

             @Override
             public void onPageScrollStateChanged(int state) {
                Log.i("", "onPageScrollStateChanged: " + state);
                if (state == ViewPager.SCROLL_STATE_IDLE) {
                   CampaignPagerFragment fragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(pager.getCurrentItem());
                   fragment.scaleImage(1);
                   if (pager.getCurrentItem() > 0) {
                      fragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(pager.getCurrentItem() - 1);
                      fragment.scaleImage(1 - RATIO_SCALE);
                   }

                   if (pager.getCurrentItem() + 1 < pager.getAdapter().getCount()) {
                      fragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(pager.getCurrentItem() + 1);
                      fragment.scaleImage(1 - RATIO_SCALE);
                   }
                }

             }
          });

//PagerAdapter

public class CampaignPagerAdapter extends FragmentStatePagerAdapter {
   SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

   public CampaignPagerAdapter(FragmentManager fm) {
      super(fm);
   }

   @Override
   public int getCount() {
      return 5;
   }

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

   @Override
   public Object instantiateItem(ViewGroup container, int position) {
      Fragment fragment = (Fragment) super.instantiateItem(container, position);
      registeredFragments.put(position, fragment);
      return fragment;
   }

   @Override
   public void destroyItem(ViewGroup container, int position, Object object) {
      registeredFragments.remove(position);
      super.destroyItem(container, position, object);
   }

   public Fragment getRegisteredFragment(int position) {
      return registeredFragments.get(position);
   }
}

例如:https://github.com/mrleolink/SimpleInfiniteCarousel,你好,有一件事情是缺失的,即 sampleFragment.scaleImage(scale)。这是 CampaignPagerFragment 中创建的一个方法,它会对该片段的根视图进行缩放。

例如:public void scaleImage(float scaleX) { rootView.setScaleY(scaleX); rootView.invalidate(); }


嗨,当我使用这段代码时,当我在第一个项目上时,左侧项目不会显示。实际上,左侧项目应该是列表中的最后一个项目,以使其成为循环。是否可以用这个代码实现呢? - Tooroop
有没有一种方法可以使下一个项目和上一个项目变得模糊,然后在焦点上时将模糊效果去除? - Mr T
在 "onPageSelected(int position)" 方法中,您可以移除模糊效果 @MrG - msevgi
什么是RATIO_SCALE? - Kaveesh Kanwal
嗨,谢谢你提供的代码。但我遇到了一个小问题:应用程序打开后,右侧页面的缩放一开始没有起作用,但在滑动之后就正常了。请问如何在应用程序运行时将左右两侧的页面设置为相等的缩放比例? - Zohidjon Akbarov
如何使屏幕外的项目响应点击事件? - oziomajnr

11

8

there is the image of my first solution

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;
        int max = pageHeight / 10;
        if (transformPos < -1)
        {
            // [-Infinity,-1)
            // This page is way off-screen to the left.
            page.setAlpha(0.5f);// to make left transparent
            page.setScaleY(0.7f);
        }
        else if (transformPos <= 1)
        {
            // [-1,1]
            page.setScaleY(1f);
        }
        else
        {
            // (1,+Infinity]
            // This page is way off-screen to the right.
            page.setAlpha(0.5f);// to make right transparent
            page.setScaleY(0.7f);
        }
    }
});

@KaveeshKanwal,它在我的应用程序中可以工作吗?你有什么问题? - Mina Farid
1
在我的情况下,它不能与片段一起工作,而是动态视图。 - Kaveesh Kanwal

5
我认为这是最简单和最清晰的解决方案。
float scaleFactor = 0.85f;
viewPager.setPageMargin(-35);
viewPager.setOffscreenPageLimit(2);
viewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
    @Override
    public void transformPage(@NonNull View page, float position) {
        page.setScaleY((1 - Math.abs(position) * (1 - scaleFactor)));
        page.setScaleX(scaleFactor + Math.abs(position) * (1 - scaleFactor));
    }
});

0
我是通过根据位置更改我的ViewPager的填充来实现这一点的。
carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, 12), 0, Utils.dpToPixels(context, paddingRequired - 12), 0); // initial padding for position 0
carouselViewHolder.carouselViewPager.setPageMargin(Utils.dpToPixels(context, 12)); // margin between pages
carouselViewHolder.carouselViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }
    @Override
    public void onPageSelected(int position) {
        if (position != 0) {
            if (position == playCardData.getPlayCards().size() - 1) {
                carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, finalPaddingRequired - 12), 0, Utils.dpToPixels(context, 12), 0);
            } else
                carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, finalPaddingRequired / 2), 0, Utils.dpToPixels(context, finalPaddingRequired / 2), 0);
        } else {
            carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, 12), 0, Utils.dpToPixels(context, finalPaddingRequired - 12), 0);
        }
    }
    @Override
    public void onPageScrollStateChanged(int state) {
    }
});

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