实现类似猫眼影片详情页电影海报滚动效果(ViewPager 两侧显示相邻item)

本文参考(ViewPager画廊效果)仿淘票票影院影片选择

这种实现方法比较简单,但是并不能像是淘票票、猫眼的电影画廊那样,一下子滚动多个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);
            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值