RecyclerView 的ViewPageLayoutManager

实现类似抖音的的全屏上下滑动翻页效果,方案有两种:

1.ViewPage

ViewPager来实现的时候,手机内存不够用的情况就会显现出来

2.RecyclerView

RecyclerView可以帮我们处理内存的回收和利用

实现过程:

1.自定义LayoutManager,并且继承LinearLayoutManager,这样就得到一个可以水平排向或者竖向排向的布局

PagerSnapHelper可以做到一次滑动翻一页,并且居中的viewpage效果

    public void onAttachedToWindow(RecyclerView view) {
        super.onAttachedToWindow(view);
        this.mPagerSnapHelper.attachToRecyclerView(view);
        this.mRecyclerView = view;
        this.mRecyclerView.addOnChildAttachStateChangeListener(this.mChildAttachStateChangeListener);
    }

2.开始播放和释放播放器的时机

重写onScrollStateChanged()函数,这里面有三种状态:

 

  • SCROLL_STATE_IDLE(空闲)

  • SCROLL_STATE_DRAGGING(拖动)

  • SCROLL_STATE_SETTLING(要移动到最后位置时)

我们需要的就是RecyclerView停止时的状态,我们就可以拿到这个View的Position.注意这里还有一个问题,当你通过这个position去拿Item会报错。打印Log,你会发现RecyclerView.getChildCount()一直为1或者会出现为2的情况。好了,我们自己来实现一个接口然后通过接口把状态传递出去。

翻页状态监听器:

public interface OnViewPagerListener {
    void onInitComplete();

    void onPageRelease(boolean var1, int var2);

    void onPageSelected(int var1, boolean var2);
}

重写LinearLayoutManager的onScrollStateChanged方法:

    public void onScrollStateChanged(int state) {
        switch(state) {
        case 0:
            View viewIdle = this.mPagerSnapHelper.findSnapView(this);
            int positionIdle = this.getPosition(viewIdle);
            if (this.mOnViewPagerListener != null && this.getChildCount() == 1) {
                this.mOnViewPagerListener.onPageSelected(positionIdle, positionIdle == this.getItemCount() - 1);
            }
            break;
        case 1:
            View viewDrag = this.mPagerSnapHelper.findSnapView(this);
            this.getPosition(viewDrag);
            break;
        case 2:
            View viewSettling = this.mPagerSnapHelper.findSnapView(this);
            this.getPosition(viewSettling);
        }

    }

3. 区分上一页还是下一页

列表的选中监听好了,我们就看看什么时候释放视频的资源,第二步中的三种状态,去打印getChildCount()的日志,你会发现getChildCount()在:

SCROLL_STATE_DRAGGING会为1

SCROLL_STATE_SETTLING为2

SCROLL_STATE_IDLE有时为1,有时为2
我们要做的是要知道在什么时候去做释放视频的操作,还要分清是释放上一页还是下一页,因为适配器adapter的position在这里不好使嘛,这里有两个方法scrollHorizontallyBy()和scrollVerticallyBy()可以拿到滑动偏移量,可以判断滑动方向

    public int scrollVerticallyBy(int dy, Recycler recycler, State state) {
        this.mDrift = dy;
        return super.scrollVerticallyBy(dy, recycler, state);
    }

    public int scrollHorizontallyBy(int dx, Recycler recycler, State state) {
        this.mDrift = dx;
        return super.scrollHorizontallyBy(dx, recycler, state);
    }
    private OnChildAttachStateChangeListener mChildAttachStateChangeListener = new OnChildAttachStateChangeListener() {
        public void onChildViewAttachedToWindow(View view) {
            if (ViewPagerLayoutManager.this.mOnViewPagerListener != null && ViewPagerLayoutManager.this.getChildCount() == 1) {
                ViewPagerLayoutManager.this.mOnViewPagerListener.onInitComplete();
            }

        }

        public void onChildViewDetachedFromWindow(View view) {
            if (ViewPagerLayoutManager.this.mDrift >= 0) {
                if (ViewPagerLayoutManager.this.mOnViewPagerListener != null) {
                    ViewPagerLayoutManager.this.mOnViewPagerListener.onPageRelease(true, ViewPagerLayoutManager.this.getPosition(view));
                }
            } else if (ViewPagerLayoutManager.this.mOnViewPagerListener != null) {
                ViewPagerLayoutManager.this.mOnViewPagerListener.onPageRelease(false, ViewPagerLayoutManager.this.getPosition(view));
            }

        }
    };

完整代码:

ViewPageLayoutManager:

public class ViewPagerLayoutManager extends LinearLayoutManager {
    private static final String TAG = "ViewPagerLayoutManager";
    private PagerSnapHelper mPagerSnapHelper;
    private OnViewPagerListener mOnViewPagerListener;
    private RecyclerView mRecyclerView;
    private int mDrift;
    private OnChildAttachStateChangeListener mChildAttachStateChangeListener = new OnChildAttachStateChangeListener() {
        public void onChildViewAttachedToWindow(View view) {
            if (ViewPagerLayoutManager.this.mOnViewPagerListener != null && ViewPagerLayoutManager.this.getChildCount() == 1) {
                ViewPagerLayoutManager.this.mOnViewPagerListener.onInitComplete();
            }

        }

        public void onChildViewDetachedFromWindow(View view) {
            if (ViewPagerLayoutManager.this.mDrift >= 0) {
                if (ViewPagerLayoutManager.this.mOnViewPagerListener != null) {
                    ViewPagerLayoutManager.this.mOnViewPagerListener.onPageRelease(true, ViewPagerLayoutManager.this.getPosition(view));
                }
            } else if (ViewPagerLayoutManager.this.mOnViewPagerListener != null) {
                ViewPagerLayoutManager.this.mOnViewPagerListener.onPageRelease(false, ViewPagerLayoutManager.this.getPosition(view));
            }

        }
    };

    public ViewPagerLayoutManager(Context context, int orientation) {
        super(context, orientation, false);
        this.init();
    }

    public ViewPagerLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        this.init();
    }

    private void init() {
        this.mPagerSnapHelper = new PagerSnapHelper();
    }

    public void onAttachedToWindow(RecyclerView view) {
        super.onAttachedToWindow(view);
        this.mPagerSnapHelper.attachToRecyclerView(view);
        this.mRecyclerView = view;
        this.mRecyclerView.addOnChildAttachStateChangeListener(this.mChildAttachStateChangeListener);
    }

    public void onLayoutChildren(Recycler recycler, State state) {
        super.onLayoutChildren(recycler, state);
    }

    public void onScrollStateChanged(int state) {
        switch(state) {
        case 0:
            View viewIdle = this.mPagerSnapHelper.findSnapView(this);
            int positionIdle = this.getPosition(viewIdle);
            if (this.mOnViewPagerListener != null && this.getChildCount() == 1) {
                this.mOnViewPagerListener.onPageSelected(positionIdle, positionIdle == this.getItemCount() - 1);
            }
            break;
        case 1:
            View viewDrag = this.mPagerSnapHelper.findSnapView(this);
            this.getPosition(viewDrag);
            break;
        case 2:
            View viewSettling = this.mPagerSnapHelper.findSnapView(this);
            this.getPosition(viewSettling);
        }

    }

    public int scrollVerticallyBy(int dy, Recycler recycler, State state) {
        this.mDrift = dy;
        return super.scrollVerticallyBy(dy, recycler, state);
    }

    public int scrollHorizontallyBy(int dx, Recycler recycler, State state) {
        this.mDrift = dx;
        return super.scrollHorizontallyBy(dx, recycler, state);
    }

    public void setOnViewPagerListener(OnViewPagerListener listener) {
        this.mOnViewPagerListener = listener;
    }
}

主Activity:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "ViewPagerActivity";
    private RecyclerView mRecyclerView;
    private MyAdapter mAdapter;
    private ViewPagerLayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

        initListener();
    }

    private void initView() {
        mRecyclerView = findViewById(R.id.recycler);

        mLayoutManager = new ViewPagerLayoutManager(this, OrientationHelper.VERTICAL);
        mAdapter = new MyAdapter();
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initListener(){
        mLayoutManager.setOnViewPagerListener(new OnViewPagerListener() {
            @Override
            public void onInitComplete() {

            }

            @Override
            public void onPageRelease(boolean isNext,int position) {
                Log.e(TAG,"释放位置:"+position +" 下一页:"+isNext);
                int index = 0;
                if (isNext){
                    index = 0;
                }else {
                    index = 1;
                }
                releaseVideo(index);
            }

            @Override
            public void onPageSelected(int position,boolean isBottom) {
                Log.e(TAG,"选中位置:"+position+"  是否是滑动到底部:"+isBottom);
                playVideo(0);
            }


            public void onLayoutComplete() {
                playVideo(0);
            }

        });
    }

    private void playVideo(int position) {
        View itemView = mRecyclerView.getChildAt(0);
        final VideoView videoView = itemView.findViewById(R.id.video_view);
        final ImageView imgPlay = itemView.findViewById(R.id.img_play);
        final ImageView imgThumb = itemView.findViewById(R.id.img_thumb);
        final RelativeLayout rootView = itemView.findViewById(R.id.root_view);
        final MediaPlayer[] mediaPlayer = new MediaPlayer[1];
        videoView.start();
        videoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
            @Override
            public boolean onInfo(MediaPlayer mp, int what, int extra) {
                mediaPlayer[0] = mp;
                Log.e(TAG,"onInfo");
                mp.setLooping(true);
                imgThumb.animate().alpha(0).setDuration(200).start();
                return false;
            }
        });
        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                Log.e(TAG,"onPrepared");

            }
        });


        imgPlay.setOnClickListener(new View.OnClickListener() {
            boolean isPlaying = true;
            @Override
            public void onClick(View v) {
                if (videoView.isPlaying()){
                    Log.e(TAG,"isPlaying:"+videoView.isPlaying());
                    imgPlay.animate().alpha(1f).start();
                    videoView.pause();
                    isPlaying = false;
                }else {
                    Log.e(TAG,"isPlaying:"+videoView.isPlaying());
                    imgPlay.animate().alpha(0f).start();
                    videoView.start();
                    isPlaying = true;
                }
            }
        });
    }

    private void releaseVideo(int index){
        View itemView = mRecyclerView.getChildAt(index);
        final VideoView videoView = itemView.findViewById(R.id.video_view);
        final ImageView imgThumb = itemView.findViewById(R.id.img_thumb);
        final ImageView imgPlay = itemView.findViewById(R.id.img_play);
        videoView.stopPlayback();
        imgThumb.animate().alpha(1).start();
        imgPlay.animate().alpha(0f).start();
    }


    class MyAdapter extends RecyclerView.Adapter{
        private int[] imgs = {R.mipmap.video11,R.mipmap.video12,R.mipmap.video13,R.mipmap.video14,R.mipmap.img_video_2};
        private int[] videos = {R.raw.video11,R.raw.video12,R.raw.video13,R.raw.video14,R.raw.video_2};
        public MyAdapter(){
        }


        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view_pager,parent,false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {






            holder.img_thumb.setImageResource(imgs[position%5]);



            holder.videoView.setVideoURI(Uri.parse("android.resource://"+getPackageName()+"/"+ videos[position%5]));
        }

        @Override
        public int getItemCount() {
            return 50;
        }

        public class ViewHolder extends RecyclerView.ViewHolder{
            ImageView img_thumb;
            VideoView videoView;
            ImageView img_play;
            RelativeLayout rootView;
            public ViewHolder(View itemView) {
                super(itemView);
                img_thumb = itemView.findViewById(R.id.img_thumb);
                videoView = itemView.findViewById(R.id.video_view);
                img_play = itemView.findViewById(R.id.img_play);
                rootView = itemView.findViewById(R.id.root_view);
            }
        }
    }
}

 

你可能感兴趣的:(android)