首先不要使用ViewPager,有很多坑!
使用RecyclerView—SnapHelper的子类PagerSnapHelper
可以实现选中item居中显示
至于SnapHelper是什么,可参考https://www.jianshu.com/p/e54db232df62
具体使用:
肯定是垂直方向的滑动,使用LinearLayoutManager
自定义LayoutManager,继承LinearLayoutManager
public class PagerLayoutManager extends LinearLayoutManager;
在构造 PagerLayoutManager 时 初始化PagerSnapHelper 得到hepler
public PagerLayoutManager(Context context) { super(context); init(context); } private PagerSnapHelper helper; private void init(Context context) { helper = new PagerSnapHelper() { @Override public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) { int position = super.findTargetSnapPosition(layoutManager, velocityX, velocityY); // ToastUtils.show(context, "当前滑动页号:" + position); return position; } }; }
重写LayoutManager的onAttachedToWindow方法 让hepler与RecyclerView进行绑定
@Override public void onAttachedToWindow(RecyclerView recyclerView) { super.onAttachedToWindow(recyclerView); helper.attachToRecyclerView(recyclerView); }
以上基本上实现了抖音布局的滑动,但是不能监听滑动到具体哪个页面。下面继续
想要拿到当前停留的item需要重写onScrollStateChanged(int state); 方法 其中state有以下几种状态
public static final int SCROLL_STATE_IDLE = 0; //空闲 静止状态
public static final int SCROLL_STATE_DRAGGING = 1; //滚动状态
public static final int SCROLL_STATE_SETTLING = 2; //动画滚动时
静止状态时就是当前页面item,可以拿到当前页面的下标position
@Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); if (state == RecyclerView.SCROLL_STATE_IDLE) { View view = helper.findSnapView(this); int position = getPosition(view); } }
拿到角标后需要传递给外层使用,自定义接口 把当前页面下标传递出去;修改后如下
public interface OnSnapChangedListener { void onSnapChanged(int position); } public void setOnSnapChangedListener(OnSnapChangedListener onSnapChangedListener) { this.onSnapChangedListener = onSnapChangedListener; }@Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); if (state == RecyclerView.SCROLL_STATE_IDLE) { View view = helper.findSnapView(this); if (view != null) { int position = getPosition(view); if (onSnapChangedListener != null && getChildCount() == 1) { onSnapChangedListener.onSnapChanged(position); } } } }
此时就可以拿到当前播放页面的信息。
下面介绍第一次初始化监听和滑动的监听:
为什么要有第一次初始化,上面已经介绍了当前页面的选中操作,那是在有滑动操作的时候才走onScrollStateChanged;
滑动监听:在滑动的时候可以对视频进行暂停或者其他的处理,正常情况也需要对下个视频进行预加载。
public interface OnViewPagerListener { //自定义监听器 /** * 初始化完成 */ void onInitComplete(); /** * 页面不可见, 释放 * * @param isNext 是否有下一个 * @param position 下标 */ void onPageRelease(boolean isNext, int position); }private int direction;/** * 监听竖直方向的相对偏移量 * * @param dy y方向位移 * @param recycler recyclerView * @param state 滑动状态 * @return */ @Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { direction = dy; return super.scrollVerticallyBy(dy, recycler, state); }private RecyclerView.OnChildAttachStateChangeListener mChildAttachStateChangeListener = new RecyclerView.OnChildAttachStateChangeListener() { @Override public void onChildViewAttachedToWindow(View view) { if (mOnViewPagerListener != null && getChildCount() == 1) { mOnViewPagerListener.onInitComplete(); //第一次初始化 } } @Override public void onChildViewDetachedFromWindow(View view) { //向上滑动还是向下滑动 if (direction >= 0) { if (mOnViewPagerListener != null) { mOnViewPagerListener.onPageRelease(true, getPosition(view)); } } else { if (mOnViewPagerListener != null) { mOnViewPagerListener.onPageRelease(false, getPosition(view)); } } } };//在这个方法里 不仅要绑定helper 也需要初始化 滑动变化监听器 @Override public void onAttachedToWindow(RecyclerView recyclerView) { super.onAttachedToWindow(recyclerView); helper.attachToRecyclerView(recyclerView); recyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener); }
到这里,所有有关抖音基础布局完成。如有不正确之处,欢迎指教,共同进步。