Android仿抖音短视频布局


首先不要使用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);
}

到这里,所有有关抖音基础布局完成。如有不正确之处,欢迎指教,共同进步。

你可能感兴趣的:(Serice)