欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

利用ViewPager实现画廊Gallery效果

程序员文章站 2022-05-15 17:17:33
...

1、 需求确认

最近做的一个小学的定制项目,谈需求的时候客户提到一个界面的效果。

客户:这个界面我们需要显示一张XX图片,但是它可以左右滑,为了知道它可以滑,需要在两边露一点比较小的图出来。

UI : 设计的原型图:
利用ViewPager实现画廊Gallery效果

这是客户提出的需求,我们作为程序员需要转换为自己的理解:

这个界面我们需要使用列表进行展示,RecycleView或者Viewpager
关键是,左右需要露一点出来,如果用RecycleView的话需要让item占满全屏,左右露一点不太好实现,如果不让item占满全屏,就会出现滑动到两个item中间的情况。
所以应该是使用Viewpager,但是Viewpager怎么露出两侧的图呢?(我在网上游弋的时候,发现这种效果的名字叫做画廊,android有个控件Gallery就是用来实现这个效果的,但是现在不建议使用了,好贴切、好立体的名字。/(ㄒoㄒ)/~~原谅自己的无知,瞬间阿Q精神上身—-又找到一个可以装B的点了,O(∩_∩)O哈哈哈~)
so,我就稍稍必应了一下(本来想说百度了一下的,但是渣渣的百度搜索,我还是喜欢用必应,尤其是必应的bg图。O(∩_∩)O哈哈哈~),用viewpager是可以做到的,只是需要利用它的两个属性。


2、利用viewpager实现画廊效果

1 、viewpager的继承关系

利用ViewPager实现画廊Gallery效果


2 、使用ViewGroup的setClipChildren(boolean clipChildren)方法

当然也可以在XML文件里面设置,属性为clipChildren

利用ViewPager实现画廊Gallery效果

在代码中使用,就是setClipChildren()
利用ViewPager实现画廊Gallery效果

这个方法或者属性的作用就是viewgroup的子view是否在它应有的边界内绘制。默认为true,在其边界内绘制。

so,我们就解决了核心的一点,怎么在两边露出图片的问题。接下来就是让切换的效果好看一点,切换的时候,把两边的图片变小一点,把中间的图片变大一点。


3 、使用viewpager的setPageTransformer(…)方法实现vp页面切换效果

利用ViewPager实现画廊Gallery效果

这个方法的作用是,设置一个ViewPager.PageTransformer,每当更改滚动位置时,将为每个附加的页面调用它。意思就是VP切换界面的时候会调用这个ViewPager.PageTransformer以实现页面切换的动画效果。

其实许多ViewPager切换效果都是通过创建一个类实现ViewPager.PageTransformer然后重写transformPage方法来实现各种切换效果,放大缩小、旋转、倒影等等


3、实战代码

1 、首先是父级布局

利用ViewPager实现画廊Gallery效果

代码

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/class_honor"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:gravity="center"
    tools:context="com.cnbs.eleclasscard.activity.growing.ClassHonorFragment">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="-30dp"
        android:layout_marginBottom="50dp"
        android:src="@mipmap/bg_growing_class_honor" />

    <android.support.v4.view.ViewPager
        android:id="@+id/class_honor_vp"
        android:layout_width="800dp"
        android:layout_height="600dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="90dp"
        android:clipChildren="false"/>


</RelativeLayout>

特别说明:这个应用是在学校特定的设备上开发的,所以我根本没有考虑适配其他的设备O(∩_∩)O~


2 、viewpager需要显示的内容

就一张图片,所以在孩子fragment的布局文件

利用ViewPager实现画廊Gallery效果

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp"
    tools:context="com.cnbs.eleclasscard.activity.growing.ClassHonorItemFragment">

  <ImageView
      android:id="@+id/class_honor_img"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:scaleType="fitXY"
      android:src="@mipmap/img_loading43"/>

</FrameLayout>

3 、实现画廊效果

1. viewpager和其父级布局都需要禁止让子view在其限制内绘制

private void initView() {
        classHonorVp.setClipChildren(false); //VP的内容可以不在限制内绘制
        classHonor.setClipChildren(false);  //VP可以不在限制内绘制
        adapter = new ClassHonorPageAdapter(getChildFragmentManager(), mContext, data); 
        classHonorVp.setAdapter(adapter);
        //实现画廊效果
        classHonorVp.setPageTransformer(true, new ZoomOutPageTransformer());   //实现需要的页面转换效果
        classHonorVp.setOffscreenPageLimit(2); //缓存页面数
        classHonorVp.setPageMargin(100); //每页的间隔
        //触摸事件反馈给viewpager
        classHonor.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return classHonorVp.dispatchTouchEvent(event);
            }
        });
    }

补上,ClassHonorPageAdapter的代码

public class ClassHonorPageAdapter extends FragmentStatePagerAdapter {
    private Activity mContext;
    private List<HonorBean> mData;

    public ClassHonorPageAdapter(FragmentManager fm, Activity context, List<HonorBean> data) {
        super(fm);
        this.mContext = context;
        this.mData = data;
    }

    public void refresh(List<HonorBean> data){
        this.mData = data;
        notifyDataSetChanged();
    }

    @Override
    public Fragment getItem(int position) {
        return ClassHonorItemFragment.newInstance(mContext,mData.get(position));
    }

    @Override
    public int getCount() {
        return mData==null?0:mData.size();
    }

  /*  @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }*/

}

2. 创建一个类实现ViewPager.PageTransformer,实现页面转换效果

 //实现当前页面放大效果
    class ZoomOutPageTransformer implements ViewPager.PageTransformer {
        private static final float MAX_SCALE = 1.0f;
        private static final float MIN_SCALE = 0.7f;

        @Override
        public void transformPage(View view, float position) {
            if (position < -1) {
                view.setScaleX(MIN_SCALE);
                view.setScaleY(MIN_SCALE);
            } else if (position <= 1) {
                float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
                view.setScaleX(scaleFactor);
                if (position > 0) {
                    view.setTranslationX(-scaleFactor * 2);
                } else if (position < 0) {
                    view.setTranslationX(scaleFactor * 2);
                }
                view.setScaleY(scaleFactor);
            } else {
                view.setScaleX(MIN_SCALE);
                view.setScaleY(MIN_SCALE);
            }

        }
    }

3. 补充一个,让左右都有图

 adapter.refresh(list);
 classHonorVp.setCurrentItem(1);

如果没有这个需求就不用,另外有时显示的效果没有处理,我们可以这样写:

classHonorVp.setCurrentItem(1);
classHonorVp.setCurrentItem(0);