利用ViewPager实现画廊Gallery效果

1、 需求确认

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

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

UI : 设计的原型图:
利用ViewPager实现画廊Gallery效果_第1张图片

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

这个界面我们需要使用列表进行展示,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张图片


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

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

利用ViewPager实现画廊Gallery效果_第3张图片

在代码中使用,就是setClipChildren()
利用ViewPager实现画廊Gallery效果_第4张图片

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

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


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

利用ViewPager实现画廊Gallery效果_第5张图片

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

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


3、实战代码

1 、首先是父级布局

利用ViewPager实现画廊Gallery效果_第6张图片

代码

<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效果_第7张图片

<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 mData;

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

    public void refresh(List 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);

你可能感兴趣的:(android,布局控件)