前言
起因
嗯。。。。这篇博文是在参加字节跳动青训营安卓基础班课程前写的,其实也能反映出我比较慌,主要是基础的东西不过关,比较担心后面的情况。所以这两天先看了一下,毕竟写过BILIBILIAS,还是有点用的。这篇博文写下也就是去给自己留个印象,归纳一下这两天的成果吧。
界面实现
我们来看看这个界面,它采用的是,ViewPager2 + Fragment 的方式实现4个页面,当然这个不是重点,就是做了个测试,来确定这种方案是否可行。
实现视频展示
这个抖音的展示是垂直滑动视频,来进行切换的,其实我当时考虑到的是可能有专门的控件,结果是我想多了,没有,无奈我去网上查了下,发现可以利用RecyclerView来做。接下来,根据网上各种资料,成功实现了,下面我来讲讲我的理解和实现。
利用RecyclerView+PagerSnapHelper实现滚动效果
首先我们要知道,RecyclerView可以去自定义布局,提供滚动,但是Item做到占满一页真的没做过,也不知道如何实现,这个时间我了解到了PagerSnapHelper。
PagerSnapHelper是SnapHelper的一个子类,让RecyclerView具备ViewPage的翻页功能,同时也具有Item居中功能,作为初学者去深究PagerSnapHelper怎么实现的显然不太现实,如果看文章的是位大佬,或者对自己的安卓功底有信心,可以去网上看看其他人的解释或者说源代码。
简单的看一下流程吧,不然用着也有点慌。
PagerSnapHelper继承自SnapHelper,而SnapHelper又继承了RecyclerView的OnFlingListener,顾名思义(哈哈,我英语很差的啦,翻译了一下)这是Fling的监听器,那么Fling是个什么东西?哈哈,往下看我也就不明白了,从这个抽象类的注释来看,这个它与滚动有关系,这也是能控制RecyclerView的Item的原因吧,有兴趣了自己看看,我就不深究了,目前的水平有限,以后来填坑。
OK,简单来讲,PagerSnapHelper和绑定RecyclerView后,就可以实现ViewPage独立翻页和吸附功能。
下面我们来看看代码
RecyclerView recyclerView = rootView.findViewById(R.id.Home_RecyclerView); snapHelper = new PagerSnapHelper(); //附着recyclerView snapHelper.attachToRecyclerView(recyclerView);
这是在fragment里写的,所以有rootView(可能是多余的话哈哈)
那么有了这个之后的话就写adapter吧,RecyclerView的适配器我就不多说了吧,不是今天的主角,我贴下代码。
嗯,不知道大家注意到没有,这个Adapter的ViewHolder是用public修饰的,这个我们后面来看看用处。
public class MyVideoAdapter extends RecyclerView.Adapter<MyVideoAdapter.ViewHolder> { private List<Video> mData; private Context mContext; private ViewHolder holder; private View rootView; public MyVideoAdapter(List<Video> mData, Context context) { this.mData = mData; this.mContext = context; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { rootView = LayoutInflater.from(mContext).inflate(R.layout.item_home_video, parent, false); holder = new ViewHolder(rootView); return holder; } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { JZDataSource jzDataSource = new JZDataSource(mData.get(position).getVideoUrl(), "我的杰酱不可能那么可爱"); holder.jzPlay.setUp(jzDataSource, JzvdStd.SCREEN_NORMAL); if (position == 0) { holder.jzPlay.startVideo(); } } @Override public int getItemCount() { return mData.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public View rootView; public JZPlay jzPlay; public ViewHolder(View view) { super(view); rootView = view; jzPlay = view.findViewById(R.id.Home_Item_JzvdStd); } } }
还没有结束,我们还需要一个东西,设置下垂直滚动,这个是我们需要的效果,当然你可以改这里为其他的方式看看,不拘泥于垂直。
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); //让recyclerView是垂直滚动 recyclerView.setLayoutManager(layoutManager);
到这里,运行一下,你的Item就是垂直的,而且是一屏一个,垂直滑动加载下一个,具备垂直效果。但是这仅仅是解决了展示性的问题,现在得把视频加进去。
在上面的代码我没有说到播放器的事情,其实适配器里已经有了呢。
下面我介绍我使用的播放器——饺子播放器,BILIBILIAS的播放器就是它。
如果按照上面的方式,把饺子播放器放入item里,仅仅是做到了视频插入,但是抖音是有自动播放的,这个怎么办?下面我在网上也找到了一个解决方案。
RecyclerView有一个方法addOnScrollListener是滚动监听器,需要实现抽象类两个的方法,其中一个onScrollStateChanged,就是我们需要的了。
//监听滚动 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); switch (newState) { case RecyclerView.SCROLL_STATE_IDLE://停止滚动 //获取snapHelper的布局 View view = snapHelper.findSnapView(layoutManager); //获取当前item int position = recyclerView.getChildAdapterPosition(view); if (currentPosition != position) { //如果当前position 和 上一次固定后的position 相同, 说明是同一个, 只不过滑动了一点点, 然后又释放了 JZPlay.releaseAllVideos(); //关闭之前的视频 RecyclerView.ViewHolder viewHolder = recyclerView.getChildViewHolder(view); //判断获取到了而且是适配的数据对象 if (viewHolder != null && viewHolder instanceof MyVideoAdapter.ViewHolder) { //播放视频 ((MyVideoAdapter.ViewHolder) viewHolder).jzPlay.startVideo(); } } currentPosition = position; break; case RecyclerView.SCROLL_STATE_DRAGGING://拖动 break; case RecyclerView.SCROLL_STATE_SETTLING://惯性滑动 break; } } @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); } });
我们看看上面代码,当滚动状态改变时,就会调用onScrollStateChanged,此时传入了newState,这个就是滚动状态。都有注释,根据item的下标来确定是否有变动。之前说ViewHolder需要public,现在我们可以发现这是为了我们去在这里使用,以此获取到当前item的ViewHolder,再通过ViewHolder来设置饺子播放器的播放状态。当切换后就将饺子播放器关闭,然后再播放当前页面的视频。
当然,这样的写法是不全面的,我们知道抖音打开是会自动播放视频的,那么现在我们回头看看适配器,有一则判断,如果判断是0,也就是第一个视频,那么就播放它。
至于切换,我们需要在生命周期里添加一下。
@Override public void onPause() { super.onPause(); JZPlay.releaseAllVideos(); }
当fragment切换不可见时会执行它关闭视频。
饺子播放器继承自定义点击效果
饺子播放器固然强大,但是它是为了播放视频而设计的,像我们这样的就需要自定义一下,比如在视频播放时,点击后暂停视频,这个是我们需要额外实现的。
当然,今晚太晚了,我就不写具体实现了,下来我把他补上,我也是刚刚自己实现了这个继承的点击效果,还是比较不错的,但是仅仅如此是不足的,等我搞定了再补充。
感谢大家看到这里
发表回复