为了账号安全,请及时绑定邮箱和手机立即绑定

仿抖音上下滑动播放视频

太多朋友对短视频,上下滚动播放视频效果比较比较研究,今天看看这个案例。

讲下大概思路,使用Recycleview配合自定义LinearLayoutManager来实现这个功能,这里着重说下自定义LinearLayoutManager的实现可以看到每当下一个项目滑入屏幕时,上面的项目会继续播放视频,而滑入的项目只有当全部进入屏幕才会播放,而且当手指抬起时,当前item会根据滑动的距离相应的自动滑入滑出,针对这种情况,就会想到使用SnapHelper

RecyclerView在24.2.0版本中新增了SnapHelper这个辅助类,利用辅助RecyclerView在滚动结束时将项目对准到某个位置。特别是列表横向滑动时,很多时候不会让列表滑到任意位置,甚至会有一定的规则限制,这时候就可以通过SnapHelper来定义对齐规则了。

SnapHelper是一个抽象类,官方提供了一个LinearSnapHelper的子类,可以让RecyclerView滚动停止时相应的项保持中间位置。25.1.0版本中官方又提供了一个PagerSnapHelper的子类,可以使RecyclerView像ViewPager一样效果,一次只能滑动一页,而且居中显示,直接使用SnapHelper可以帮助RecyclerView滑动完成后进行对齐操作,让item的侧边对齐或者居中对齐,这样实现上下滑动进行视频切换。这里有SnapHelper的详解

2,正式撸代码:1。首先定义一个接口,用于执行item的相关操作

公共接口OnViewPagerListener { 
    / * 初始化完成* / 
    void onInitComplete(); 
    / *释放的监听器* / 
    void onPageRelease(boolean isNext,int position); 
    / *的监听器以及判断是否可以滑动到底部* / 
    void onPageSelected(int position,boolean isBottom); 
} ```

2.继承LinearLayoutManager,对滑入滑出的项目某些1中接口里面的方法

导入android.content.Context; 导入android.support.annotation.NonNull; 导入android.support.v7.widget.LinearLayoutManager; 导入android.support.v7.widget.PagerSnapHelper; 导入android.support.v7.widget.RecyclerView; 导入android.view.View;

公共类MyLayoutManager扩展LinearLayoutManager实现RecyclerView.OnChildAttachStateChangeListener {private int mDrift; //位移,用于判断移动方向的专有PagerSnapHelper mPagerSnapHelper; 私人OnViewPagerListener mOnViewPagerListener; 公共MyLayoutManager(上下文上下文){super(context); } public MyLayoutManager(上下文上下文,int方向,布尔反向布局){超级(上下文,方向,reverseLayout);mPagerSnapHelper = new PagerSnapHelper(); } @覆盖公共无效onAttachedToWindow(RecyclerView视图){view.addOnChildAttachStateChangeListener(本);

    mPagerSnapHelper.attachToRecyclerView(view); 
    super.onAttachedToWindow(view); 
}

//当项目添加进来了调用这个方法// @覆盖公共无效onChildViewAttachedToWindow(@NonNull查看视图){

//播放视频操作即将要播放的是上一个视频还是下一个视频int position = getPosition(view); if(0 ==位置){if(mOnViewPagerListener!= null){mOnViewPagerListener.onPageSelected(getPosition(view),false);}}}} public void setOnViewPagerListener(OnViewPagerListener mOnViewPagerListener){this.mOnViewPagerListener = mOnViewPagerListener; } @覆盖公共无效onScrollStateChanged(INT状态){开关(状态){情况下RecyclerView.SCROLL_STATE_IDLE:Viewview = mPagerSnapHelper.findSnapView(本); int position = getPosition(view);如果(mOnViewPagerListener!= null){mOnViewPagerListener.onPageSelected(position,position == getItemCount()-1);}

//位置—部分----》播放break; } super.onScrollStateChanged(状态);} @覆盖公共无效onChildViewDetachedFromWindow(@NonNull视图视图){

//暂停播放操作
if(mDrift> = 0){
if(mOnViewPagerListener!= null)
mOnViewPagerListener.onPageRelease(true,getPosition(view));
} else {
如果(mOnViewPagerListener!= null)
mOnViewPagerListener.onPageRelease(false,getPosition(view));
}
}

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

@Override
public boolean canScrollVertically() {
    return true;
}

}

3.接下来就是正常使用recycleview了 配合原生VideoView 播放视频,切换时先用一张截图盖住视频,视频渲染成功再隐藏截图,感觉上是无缝切换(这里是原生播放器初始加载视频会黑屏,如果用更高级的播放器可能不会有这个问题)

导入android.annotation.TargetApi; 导入android.content.Context; 导入android.media.MediaPlayer; 导入android.net.Uri; 导入android.os.Build; 导入android.os.Bundle; 导入android.support.v7.app.AppCompatActivity; 导入android.support.v7.widget.OrientationHelper; 导入android.support.v7.widget.RecyclerView; 导入android.util.Log; 导入android.view.LayoutInflater; 导入android.view.View; 导入android.view.ViewGroup; 导入android.widget.ImageView; 导入android.widget.RelativeLayout; 导入android.widget.VideoView;

公共类MainActivity扩展了AppCompatActivity {private static final String TAG =“ douyin”; 私人RecyclerView mRecyclerView; 私有MyAdapter mAdapter; MyLayoutManager2 myLayoutManager; @Override protected void onCreate(捆绑的saveInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initListener();}私有无效initView(){mRecyclerView = findViewById(R.id.recycler);myLayoutManager = new MyLayoutManager2(this,OrientationHelper.VERTICAL,false);mAdapter =新的MyAdapter(this); mRecyclerView.setLayoutManager(myLayoutManager); mRecyclerView.setAdapter(mAdapter); } private void initListener(){

    myLayoutManager.setOnViewPagerListener(new OnViewPagerListener() {
        @Override
        public void onInitComplete() {

        }

        @覆盖
        公共无效onPageRelease(布尔isNext,INT位置){ 
            Log.e(TAG, “释放位置:” +位置+ “下一页:” + isNext); 
            int索引= 0; 
            如果(isNext){ 
                索引= 0; 
            } else { 
                index = 1; 
            } 
            releaseVideo(index); 
        } 

        @覆盖
        公共无效使用onPageSelected(INT位置,布尔底部){ 
            Log.e(TAG, “选择位置:” +位置+ “下一页:” +底部); 

            playVideo(0); 
        } 
    }); 
}

class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private int[] imgs = {R.mipmap.img_video_1, R.mipmap.img_video_2, R.mipmap.img_video_3, R.mipmap.img_video_4, R.mipmap.img_video_5, R.mipmap.img_video_6, R.mipmap.img_video_7, R.mipmap.img_video_8};
    private int[] videos = {R.raw.video_1, R.raw.video_2, R.raw.video_3, R.raw.video_4, R.raw.video_5, R.raw.video_6, R.raw.video_7, R.raw.video_8};
    private int index = 0;
    private Context mContext;

    public MyAdapter(Context context) {
        this.mContext = context;
    }


    @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[index]);
        holder.videoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + videos[index]));
        index++;
        if (index >= 7) {
            index = 0;
        }
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView img_thumb;
        VideoView videoView;
        ImageView img_play; 
        RelativeLayout rootView; 

        公共ViewHolder(查看itemView){ 
            超级(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); 
        } 
    } 
} 

private void releaseVideo(int索引){ 
    查看itemView = mRecyclerView.getChildAt(索引);
    最终VideoView videoView = itemView.findViewById(R.id.video_view);
    最终的ImageView imgThumb = itemView.findViewById(R.id.img_thumb); 
    最终的ImageView imgPlay = itemView.findViewById(R.id.img_play); 
    videoView.stopPlayback();
    imgThumb.animate()。alpha(1)
    .start ();imgPlay.animate()。alpha(0f)    .start();
} 

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)私有无效playVideo(int position){查看itemView = mRecyclerView.getChildAt(position);最终FullWindowVideoView videoView = itemView.findViewById(R.id.video_view);最终的ImageView imgPlay = itemView.findViewById(R.id.img_play); 最终的ImageView imgThumb = itemView.findViewById(R.id.img_thumb); 最终RelativeLayout rootView = itemView.findViewById(R.id.root_view);最终的MediaPlayer [] mediaPlayer =新的MediaPlayer [1]; videoView.setOnPreparedListener(新MediaPlayer.OnPreparedListener(){ @ 覆盖公共无效onPrepared(MediaPlayer的熔点){ } }); videoView.setOnInfoListener(新MediaPlayer.OnInfoListener(){ @

        覆盖公共布尔onInfo(MediaPlayer的浓度,INT,整型附加){ 
            MEDIAPLAYER [0] =熔点;
            mp.setLooping(真)
            。imgThumb.animate()α(0).setDuration(200)。开始();
            返回假
        } 
    });

    videoView.start();

    imgPlay.setOnClickListener(新View.OnClickListener(){ 
        boolean isPlaying = true;)。)。 )。))))))))))))))))。)

        @覆盖
        公共无效的onClick(查看v){ 
            如果(videoView.isPlaying()){ 
                imgPlay.animate()α(0.7F) 。
                ;;;; videoView .pause();
                IsPlaying模块= FALSE;
            }其他{ 
                imgPlay.animate()。alpha(0f)
                .start(); videoView.start();
                isPlaying = true;
            } 
        } 
    } ;;
}}”
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消