这种实现方法比较简单,但是并不能像是淘票票、猫眼的电影画廊那样,一下子滚动多个item,因为ViewPager本质上就是一次只能划过一个item(此外这种方法,必须设置所有的条目作为缓存mViewPager.setOffscreenPageLimit(TOTAL_COUNT),这样性能低)
一次划过多个item,需要使用RecyclerView+SnapHelp(LinearSnapHelper)来实现,这种效果看上去会更好,具体实现,看这篇博客:实现类似猫眼影片详情页电影海报滚动效果(RcyclerView+LinearSnapHelper )
效果
第一行为ViewPager实现效果
第二行为RcyclerView+LinearSnapHelper 实现效果
一、 布局写法
a. 必须给ViewPager包裹一层布局,例如LinearLayout,并且在LinearLayout添加属性android:clipChildren=”false”
b.ViewPager也必须添加属性android:clipChildren=”false”
c.ViewPager要显示在父布局中间区域,他的宽度不要再math_parent,一般为电影海报的宽度
d.item布局正常写就可以了,只是宽度注意是海报宽度就行,别match_parent
布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.custom.view.gallerydemo.MainActivity">
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:clipChildren="false">
<com.custom.view.gallerydemo.ClipViewPager
android:id="@+id/viewpager"
android:layout_width="100dp"
android:layout_height="170dp"
android:layout_gravity="center"
android:clipChildren="false"/>
</LinearLayout>
</android.support.v7.widget.LinearLayoutCompat>
item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="170dp">
<ImageView
android:id="@+id/iv"
android:src="@drawable/iv3"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:layout_width="90dp"
android:layout_height="150dp"/>
</RelativeLayout>
二、java写法
a. ClipAdapter正常写就可以了
b. mViewPager.setPageMargin(35);//设置间距,这个间距是两个item之间的间隔
c.mViewPager.setOffscreenPageLimit(TOTAL_COUNT);//设置缓存数量为总的item个数
d.记得设置viewpager的父布局的触摸事件,让他的触摸事件等同于Viewpager的行为,不然的话,你触摸边缘两侧的item不会滑动
ClipAdapter adapter = new ClipAdapter(this);
mViewPager = findViewById(R.id.viewpager);
mLl = findViewById(R.id.ll);
mViewPager.setPageMargin(35);//设置间距
mViewPager.setOffscreenPageLimit(8);//设置缓存数量
mViewPager.setAdapter(adapter);
mViewPager.setPageTransformer(false, new ScaleVieapagerTransform());//选中放大动画效果,引入“ compile 'com.youth.banner:banner:1.4.10'”,里面有很多ViewPager动画效果
mLl.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mViewPager.dispatchTouchEvent(event);
}
});
上边已经实现了,ViewPager两边Item显示的功能,还有一个需求,就是点击任意一个Item,让这个Item 居中
三、点击任意一个Item,让这个Item 居中
实现这个需求,需要自定义ViewPager,也就是上面用到的ClipViewPager,直接看注释
public class ClipViewPager extends ViewPager {
public ClipViewPager(Context context) {
super(context);
}
public ClipViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
// 根据手指触摸点,得到你所触摸的View
View view = viewoOfClickOnScreen(ev);
if (view != null) {
// 根据你所触摸的View,得到你所触摸的View的位置
int index = indexOfChild(view);
if (getCurrentItem() != index) {
// 跳转到这个View
setCurrentItem(indexOfChild(view));
}
}
}
return super.dispatchTouchEvent(ev);
}
/**
* 找到屏幕上显示的所有子条目,得到他们在屏幕中的坐标,与手指触摸点比对,返回你所点到的View
* @param ev
* @return
*/
private View viewoOfClickOnScreen(MotionEvent ev) {
int childCount = getChildCount();
int[] location = new int[2];
for (int i = 0; i < childCount; i++) {
// 遍历每一个ViewPager的子View
View v = getChildAt(i);
// 得到子View在屏幕上的坐标值,存在location中
v.getLocationOnScreen(location);
// 注意:这个X坐标为,View的最左侧坐标
int minX = location[0];
int minY = getTop();
// 得到view的最右侧坐标
int maxX = location[0] + v.getWidth();
int maxY = getBottom();
// 手指触摸的坐标
float x = ev.getX();
float y = ev.getY();
// 手指触摸坐标,在哪一个子View的范围之内,那么就返回这个View
if ((x > minX && x < maxX) && (y > minY && y < maxY)) {
return v;
}
}
return null;
}
}
附:放大缩小ViewPager动画
mViewPager.setPageTransformer(true, new ViewPager.PageTransformer() {
@Override
public void transformPage(View page, float position) {
float scale = 1f - ((float) (0.3 * Math.abs(position)));
// 不写下面的if,得到的是多级缩放,写了之后,是单级缩放
if (scale<0.7f){
scale=0.7f;
}
page.setScaleY(scale);
page.setScaleX(scale);
}
});