根据图片高度动态改变ViewPager高度方法的两种方式对比: PageTransformer& OnPageChangeListener

    xiaoxiao2025-08-03  15

    前言:师兄让我先试手一下完成蘑菇街index页面,在做到实现“根据图片高度动态改变ViewPager高度”时,我遇到了选择viewpager api的问题,然后自己试着对此进行了一点总结。

    首先我根据师兄的提示使用了PageTransformer这个接口,但是发现用它写出来的效果会有一些细微的bug,其本身对用户体验的影响很小,但我想试试用另外一个接口OnPageChangeListener然后最终实现了相同的效果。

    这里先对比一下两个接口内的方法

    PageTransformer

    public void transformPage(View view, float position)

    它只有这一个方法,如下:

    这个方法的参数有两个view和position,这个方法中的view指的是viewpager的直接操作的view,而position指的是相对于当前页面的位置:

    position

    position取值范围(-∞,+∞)当前值大于0且正在增大,说明这个page正在向右滑,若大于0切正在减小说明正在向左滑,小于0的情况同理。 PageTransformer这个借口是viewpager的内部类,实现这个借口的方法后,使用 :

    mViewPager.setPageTransformer(true, new ZoomOutPageTransformer());

    可以为每个item设置基于position变化的效果。

    由于viewpager这个viewgroup的特殊性,它只会存当前页面加左右两个页面,共三个页面,所以当我们滑动页面时,如果在transformPage里log输出position,我们实际上能有同时收到3个item返回的position,不过因为他们位置的不同,position的变化范围不同,因此也较容易区分。

    再观察transformPage这个方法,参数里只有view这个参数能获得当前item相对于adapter的位置,当我们要根据每个item的自身特性去做动画时,可以用ViewGroup中的getChildAt()方法来获得当前的View,用viewpager的方法getCurrentItem()来获得当前的item位于index的位置。

    getCurrentItem()

    这个方法的的返回值是当前的“趋势页面”,简言之就是你手指离开屏幕后viewpager停留的那个页面,此方法如下:

    它返值回的是一个 int的值。

    getChildAt(int a)

    这个方法返回index里a位置的view,由于viewpager只缓存三个页面,所以单数一般不会大于2,若要取当前页面,则分情况:

    a=0:getChildAt(0);

    a>0: getChildAt(1);

    OnPageChangeListener

    此接口内有三个方法

    1.public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);

    2.public void onPageSelected(int position);

    3.public void onPageScrollStateChanged(int state);

    其中第一个方法所提供的参数最为丰富

    第一个参数,position,代表当前正在显示的第一个页面的索引,如果positionOffset不等于0,那么第position+1个页面将被显示。

    第二个参数,positionOffset,代表position页面的偏移,取值范围是[0,1)。这是一个偏移百分比,类似于transformPage()中的position,但是有区别。

    第三个参数,positionOffsetPixels,和第二个意义差不多,只不过单位是像素,偏移的像素值。

    当我用log输出position 和getCurrentItem()的值时,发现如下:

    上图是我在向右滑动ViewPager时log出的内容:可以发现一个规律:getCurrentItem()的返回值变为1时,position还是0。

    上图是我在向左滑动ViewPager时log出的内容:position是0时,getCurrentItem()的返回值还是1,后变为0。

    即,getCurrentItem()的返回值是当你手指离开屏幕时会做一判断,页面“即将“停留在第几页,则手指离开的一瞬间返回值为该页的索引。position则是当你向左滑动时,开始滑动的一瞬间就会将position置为(滑动前position)-1;向右滑动则会当页面完全填充viewpager时将position置为(滑动前position)+1。

    下面的代码是我实现能屈能伸ViewPager使用的OnPageChangeListener接口:

    ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { Log.e("---viewpager", "position:" + position + "--getCurrentItem:" + mViewPager.getCurrentItem()); if (mViewPager.getChildAt(1) != null) { // ((RelativeLayout) mViewPager.getChildAt(1)).getChildAt(0).getHeight(); LinearLayout.LayoutParams ls = (LinearLayout.LayoutParams) mViewPager.getLayoutParams(); ls.height = (int) (heights[position] - (Math.abs(positionOffset) * (heights[position] - heights[position + 1]))); mViewPager.setLayoutParams(ls); float sc = positionOffset * ((float) heights[position + 1] / (float) heights[position] - 1) + 1; if (position < mImageViews.size() - 1) { if (heights[position] < heights[position + 1]) { float scale = ((float) ls.height) / heights[position]; mImageViews.get(position).setScaleX(scale); mImageViews.get(position).setScaleY(1); scale = heights[position + 1] / (float) ls.height; mImageViews.get(position + 1).setScaleX(1); mImageViews.get(position + 1).setScaleY(scale); // mImageViews.get(position + 1).getDrawable().setBounds(new Rect(0,top,ls.width,bottom)); } else { float scale = ((float) ls.height) / heights[position + 1]; mImageViews.get(position + 1).setScaleX(scale); mImageViews.get(position + 1).setScaleY(1); scale = heights[position] / (float) ls.height; mImageViews.get(position).setScaleX(1); mImageViews.get(position).setScaleY(scale); // mImageViews.get(position).getDrawable().setBounds(new Rect(0,top,ls.width,bottom)); } } // } } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } };

    总结:根据上面的分析,我们应该可以得出胡结论:当我们需求的viewpager的变化与当面page的属性无关(即无论当前是第几个页面我们总是做相同的变换)时用PageTransformer较方便;当viewpager的变化与当前page有关时用 OnPageChangeListener较方便;

    转载请注明原文地址: https://ju.6miu.com/read-1301350.html
    最新回复(0)