最近做的一个小学的定制项目,谈需求的时候客户提到一个界面的效果。
客户:这个界面我们需要显示一张XX图片,但是它可以左右滑,为了知道它可以滑,需要在两边露一点比较小的图出来。
这是客户提出的需求,我们作为程序员需要转换为自己的理解:
这个界面我们需要使用列表进行展示,RecycleView或者Viewpager
关键是,左右需要露一点出来,如果用RecycleView的话需要让item占满全屏,左右露一点不太好实现,如果不让item占满全屏,就会出现滑动到两个item中间的情况。
所以应该是使用Viewpager,但是Viewpager怎么露出两侧的图呢?(我在网上游弋的时候,发现这种效果的名字叫做画廊,android有个控件Gallery就是用来实现这个效果的,但是现在不建议使用了,好贴切、好立体的名字。/(ㄒoㄒ)/~~原谅自己的无知,瞬间阿Q精神上身—-又找到一个可以装B的点了,O(∩_∩)O哈哈哈~)
so,我就稍稍必应了一下(本来想说百度了一下的,但是渣渣的百度搜索,我还是喜欢用必应,尤其是必应的bg图。O(∩_∩)O哈哈哈~),用viewpager是可以做到的,只是需要利用它的两个属性。
当然也可以在XML文件里面设置,属性为clipChildren
这个方法或者属性的作用就是viewgroup的子view是否在它应有的边界内绘制。默认为true,在其边界内绘制。
so,我们就解决了核心的一点,怎么在两边露出图片的问题。接下来就是让切换的效果好看一点,切换的时候,把两边的图片变小一点,把中间的图片变大一点。
这个方法的作用是,设置一个ViewPager.PageTransformer,每当更改滚动位置时,将为每个附加的页面调用它。意思就是VP切换界面的时候会调用这个ViewPager.PageTransformer以实现页面切换的动画效果。
其实许多ViewPager切换效果都是通过创建一个类实现ViewPager.PageTransformer然后重写transformPage方法来实现各种切换效果,放大缩小、旋转、倒影等等
代码
<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~
就一张图片,所以在孩子fragment的布局文件
<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>
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);