• 仿抖音上下滑动播放视频


    不少朋友对短视频,上下滑动播放视频效果比较比较感兴趣,今天看看这个案例。

    1、效果图:


    在这里插入图片描述

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

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

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

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

    public interface OnViewPagerListener {
        /*初始化完成*/
        void onInitComplete();
        /*释放的监听*/
        void onPageRelease(boolean isNext, int position);
        /*选中的监听以及判断是否滑动到底部*/
        void onPageSelected(int position, boolean isBottom);
    }
    

    2.继承LinearLayoutManager ,对滑入滑出的item回调1中接口里面的方法

    import android.content.Context;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.PagerSnapHelper;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    public class MyLayoutManager extends LinearLayoutManager implements RecyclerView.OnChildAttachStateChangeListener {
        private int mDrift;//位移,用来判断移动方向
    
        private PagerSnapHelper mPagerSnapHelper;
        private OnViewPagerListener mOnViewPagerListener;
    
        public MyLayoutManager(Context context) {
            super(context);
        }
    
        public MyLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super(context, orientation, reverseLayout);
            mPagerSnapHelper = new PagerSnapHelper();
        }
    
        @Override
        public void onAttachedToWindow(RecyclerView view) {
    
            view.addOnChildAttachStateChangeListener(this);
            mPagerSnapHelper.attachToRecyclerView(view);
            super.onAttachedToWindow(view);
        }
    //当Item添加进来了  调用这个方法
    
        //
        @Override
        public void onChildViewAttachedToWindow(@NonNull View view) {
    //        播放视频操作 即将要播放的是上一个视频 还是下一个视频
            int position = getPosition(view);
            if (0 == position) {
                if (mOnViewPagerListener != null) {
                    mOnViewPagerListener.onPageSelected(getPosition(view), false);
                }
    
            }
        }
    
        public void setOnViewPagerListener(OnViewPagerListener mOnViewPagerListener) {
            this.mOnViewPagerListener = mOnViewPagerListener;
        }
    
        @Override
        public void onScrollStateChanged(int state) {
            switch (state) {
                case RecyclerView.SCROLL_STATE_IDLE:
                    View view = mPagerSnapHelper.findSnapView(this);
                    int position = getPosition(view);
                    if (mOnViewPagerListener != null) {
                        mOnViewPagerListener.onPageSelected(position, position == getItemCount() - 1);
    
                    }
    //                postion  ---回调 ----》播放
    
    
                    break;
            }
            super.onScrollStateChanged(state);
        }
    
        @Override
        public void onChildViewDetachedFromWindow(@NonNull View view) {
    //暂停播放操作
            if (mDrift >= 0) {
                if (mOnViewPagerListener != null)
                    mOnViewPagerListener.onPageRelease(true, getPosition(view));
            } else {
                if (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 播放视频,切换时先用一张截图盖住视频,视频渲染成功再隐藏截图,感觉上是无缝切换(这里是原生播放器初始加载视频会黑屏,如果用更高级的播放器可能不会有这个问题)

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.media.MediaPlayer;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.OrientationHelper;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.VideoView;
    
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "douyin";
        private RecyclerView mRecyclerView;
        private MyAdapter mAdapter;
        MyLayoutManager2 myLayoutManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            initListener();
        }
    
        private void initView() {
            mRecyclerView = findViewById(R.id.recycler);
            myLayoutManager = new MyLayoutManager2(this, OrientationHelper.VERTICAL, false);
    
            mAdapter = new MyAdapter(this);
            mRecyclerView.setLayoutManager(myLayoutManager);
            mRecyclerView.setAdapter(mAdapter);
    
        }
    
        private void initListener() {
            myLayoutManager.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 bottom) {
                    Log.e(TAG, "选择位置:" + position + " 下一页:" + bottom);
    
                    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;
    
                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);
                }
            }
        }
    
        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();
        }
    
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        private void playVideo(int position) {
            View itemView = mRecyclerView.getChildAt(position);
            final FullWindowVideoView 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.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
    
                }
            });
            videoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
                @Override
                public boolean onInfo(MediaPlayer mp, int what, int extra) {
                    mediaPlayer[0] = mp;
                    mp.setLooping(true);
                    imgThumb.animate().alpha(0).setDuration(200).start();
                    return false;
                }
            });
    
            videoView.start();
    
            imgPlay.setOnClickListener(new View.OnClickListener() {
                boolean isPlaying = true;
    
                @Override
                public void onClick(View v) {
                    if (videoView.isPlaying()) {
                        imgPlay.animate().alpha(0.7f).start();
                        videoView.pause();
                        isPlaying = false;
                    } else {
                        imgPlay.animate().alpha(0f).start();
                        videoView.start();
                        isPlaying = true;
                    }
                }
            });
        }
    
    }
    

    原创作者:庞哈哈哈12138,原文:https://www.jianshu.com/p/3a043cd4eb1f

    欢迎关注我的微信公众号「码农突围」,分享Python、Java、大数据、机器学习、人工智能等技术,关注码农技术提升•职场突围•思维跃迁,20万+码农成长充电第一站,陪有梦想的你一起成长。

  • 相关阅读:
    Pycharm Debug调试心得
    看了一些东西,发现一些用css实现一些东西的小技巧就记录下来
    使用js创建10*10方块
    用JS获取窗口和元素的大小
    jQuery笔记
    DOM学习中的小笔记
    常用的sql语句
    C#比较两个字符串的相似度【转】
    .net Core学习笔记之MemoryCache
    初学nodejs之安装Express中遇到的问题: error: option `-v, --view <engine>' argument missing
  • 原文地址:https://www.cnblogs.com/hejunlin/p/12458577.html
Copyright © 2020-2023  润新知