视频

作者: 夜沐下的星雨 | 来源:发表于2020-09-13 18:06 被阅读0次

    在我们平常使用视频是使用饺子视频,或者自定义视频
    今天我使用了一个GSYVideoPlaver (实现了多功能的视频播放器)的依赖。通过它自定义自己所需要的功能(视频,广告视频自动播放器)
    如下图:创建的模块:
    每次使用只需要在app 中 implementation project(path:':libvideo')即可


    video.png

    使用依赖:

      implementation 'com.shuyu:GSYVideoPlayer:7.1.5'
    

    使用了WDSVideo 继承StandardGSYVideoPlayer创建自定义视频播放器

    
    public class WDSVideo extends StandardGSYVideoPlayer {
    
       //图片控件
        private ImageView mCoverImage;
    
        public WDSVideo(Context context, Boolean fullFlag) {
            super(context, fullFlag);
        }
    
        public WDSVideo(Context context) {
            super(context);
        }
    
        public WDSVideo(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void init(Context context) {
           // super.init(context);
    
    
            // GSYVideoView int
            if(getActivityContext() != null) {
                this.mContext = getActivityContext();
            } else {
                this.mContext = context;
            }
    
            initInflate(mContext);
    
            mTextureViewContainer = (ViewGroup) findViewById(R.id.surface_container);
            if (isInEditMode())
                return;
            mScreenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
            mScreenHeight = mContext.getResources().getDisplayMetrics().heightPixels;
            mAudioManager = (AudioManager) mContext.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
    
    
    
            // GSYVideoControlView
            mStartButton = findViewById(R.id.start);
            mTitleTextView = (TextView) findViewById(R.id.title);
            mBackButton = (ImageView) findViewById(R.id.back);
            mFullscreenButton = (ImageView) findViewById(R.id.fullscreen);
            mProgressBar = (SeekBar) findViewById(R.id.progress);
            mCurrentTimeTextView = (TextView) findViewById(R.id.current);
            mTotalTimeTextView = (TextView) findViewById(R.id.total);
            mBottomContainer = (ViewGroup) findViewById(R.id.layout_bottom);
            mTopContainer = (ViewGroup) findViewById(R.id.layout_top);
            mBottomProgressBar = (ProgressBar) findViewById(R.id.bottom_progressbar);
            mThumbImageViewLayout = (RelativeLayout) findViewById(R.id.thumb);
            mLockScreen = (ImageView) findViewById(R.id.lock_screen);
    
            mLoadingProgressBar = findViewById(R.id.loading);
    
    
            if (isInEditMode())
                return;
    
            if (mStartButton != null) {
                mStartButton.setOnClickListener(this);
            }
    
            if (mFullscreenButton != null) {
                mFullscreenButton.setOnClickListener(this);
                mFullscreenButton.setOnTouchListener(this);
            }
    
            if (mProgressBar != null) {
                mProgressBar.setOnSeekBarChangeListener(this);
            }
    
            if (mBottomContainer != null) {
                mBottomContainer.setOnClickListener(this);
            }
    
            if (mTextureViewContainer != null) {
                mTextureViewContainer.setOnClickListener(this);
                mTextureViewContainer.setOnTouchListener(this);
            }
    
            if (mProgressBar != null) {
                mProgressBar.setOnTouchListener(this);
            }
    
            if (mThumbImageViewLayout != null) {
                mThumbImageViewLayout.setVisibility(GONE);
                mThumbImageViewLayout.setOnClickListener(this);
            }
            if (mThumbImageView != null && !mIfCurrentIsFullscreen && mThumbImageViewLayout != null) {
                mThumbImageViewLayout.removeAllViews();
                resolveThumbImage(mThumbImageView);
            }
    
            if (mBackButton != null)
                mBackButton.setOnClickListener(this);
    
            if (mLockScreen != null) {
                mLockScreen.setVisibility(GONE);
                mLockScreen.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mCurrentState == CURRENT_STATE_AUTO_COMPLETE ||
                                mCurrentState == CURRENT_STATE_ERROR) {
                            return;
                        }
                        lockTouchLogic();
                        if (mLockClickListener != null) {
                            mLockClickListener.onClick(v, mLockCurScreen);
                        }
                    }
                });
            }
            if (getActivityContext() != null) {
                mSeekEndOffset = CommonUtil.dip2px(getActivityContext(), 50);
            }
            // GSYBaseVideoPlayer
            mSmallClose = findViewById(R.id.small_close);
    
            //StandardGSYVideoPlayer
    
            if (mBottomProgressDrawable != null) {
                mBottomProgressBar.setProgressDrawable(mBottomProgressDrawable);
            }
    
            if (mBottomShowProgressDrawable != null) {
                mProgressBar.setProgressDrawable(mBottomProgressDrawable);
            }
    
            if (mBottomShowProgressThumbDrawable != null) {
                mProgressBar.setThumb(mBottomShowProgressThumbDrawable);
            }
            mCoverImage = new ImageView(getContext());
            mCoverImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
            setThumbImageView(mCoverImage);
        }
    
    
        public ImageView getCoverView(){
            return mCoverImage;
        }
    
        @Override
        protected void startPrepare() {
            super.startPrepare();
        }
    
        @Override
        public int getLayoutId() {
            return R.layout.lib_video_layout;
        }
        // 自定义 开始/ 暂停/ 错误的图标
        @Override
        protected void updateStartImage() {
            if (mStartButton instanceof ENPlayView) {
                ENPlayView enPlayView = (ENPlayView) mStartButton;
                enPlayView.setDuration(500);
                if (mCurrentState == CURRENT_STATE_PLAYING) {
                    enPlayView.play();
                } else if (mCurrentState == CURRENT_STATE_ERROR) {
                    enPlayView.pause();
                } else {
                    enPlayView.pause();
                }
            } else if (mStartButton instanceof ImageView) {
                ImageView imageView = (ImageView) mStartButton;
                if (mCurrentState == CURRENT_STATE_PLAYING) {
                    imageView.setImageResource(R.drawable.video_click_pause_selector);
                } else if (mCurrentState == CURRENT_STATE_ERROR) {
                    imageView.setImageResource(R.drawable.video_click_error_selector);
                } else {
                    imageView.setImageResource(R.drawable.video_click_play_selector);
                }
            }
        }
        public boolean isInInPause(){
            return (mCurrentState >= 0 && mCurrentState == CURRENT_STATE_PAUSE);
        }
    
    }
    
    

    创建滚动视频监听器:

    //视频播放
    public class MkVideoScrollListener extends RecyclerView.OnScrollListener {
        int firstVisibleItem;
        int lastVisibleItem;
        LinearLayoutManager linearLayoutManager;
        private String tag;
        public MkVideoScrollListener(LinearLayoutManager linearLayoutManager){
            this.linearLayoutManager=linearLayoutManager;
        }
    
        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            firstVisibleItem =linearLayoutManager.findFirstVisibleItemPosition();
            lastVisibleItem=linearLayoutManager.findLastVisibleItemPosition();
    
            //如果大于0说明播放了
            if (GSYVideoManager.instance().getPlayPosition()>=0&&GSYVideoManager.instance().getPlayTag().equals(tag)){
                //当前播放的位置
                int position = GSYVideoManager.instance().getPlayPosition();
                //对应的播放列表TAG
                if ((position<firstVisibleItem||position>lastVisibleItem)){
                    //如果滑出去了上面和下面就是否,和今日头条一样
                    //是否全屏
                    if (!GSYVideoManager.isFullState((Activity) recyclerView.getContext())){
                        GSYVideoManager.releaseAllVideos();
                        recyclerView.getAdapter().notifyItemChanged(position);
                    }
                }
            }
        }
    
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState==RecyclerView.SCROLL_STATE_IDLE){
                play(recyclerView);
            }
        }
        /**
         *
         * 从第一可见的position  到最后一个可见的position 挨个遍历
         *
         * 通过 position 找到 对应的item view
         *
         * 在通过 item view 找到 holder 对象
         *
         *
         * 如果这个holder 是一个视频广告的holder
         *          如果这个item 视频播放器全部可见 那么通过这个item view 找到 对应的播放器控件,然后调用start 播放
         *
         */
        private void play(RecyclerView recyclerView) {
    
            // 遍历第一个可见 item 和 最后一个可见item 之间的 是否有 视频广告item
            for (int i = firstVisibleItem; i <= lastVisibleItem; i++) {
    
                View itemView = linearLayoutManager.findViewByPosition(i);// 根据 position  找到 item view;
                if (itemView==null){
                    return;
                }
                RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(itemView); // 更具 item  view 找到对应 holder
    
                if(holder instanceof MkAutoPlayVideoHolder){ // 如果这个holder 实现了这个接口,意味着这个holder 对应的item 里面的视频会自动播放
    
                    WDSVideo video =  ((MkAutoPlayVideoHolder) holder).getVideoVIew();
    
    
                    int itemViewTop = itemView.getTop(); // item 在 recycler view 中的 top
    
                    int videoHeight = video.getHeight();// 视频控件的高度
    
                    int videoTopYInRecyclerView = itemViewTop + video.getTop(); // video view 在 recycler view (祖宗容器) 的 top 值
    
    
                    if (videoTopYInRecyclerView < 0) { // 如果video view 顶部有一部分不在recycler view 里面
                        // 顶部不在 recycler  view 里面的部分小于制定的值,那么播放
                        if (Math.abs(videoTopYInRecyclerView) <= getPlayOrStopThreshold(videoHeight)) {
                            if(video.isInInPause()){
                                video.onVideoResume(false);
                            }else if(!video.isInPlayingState()){
                                video.startPrepare();
                            }
                            break;
                        }else{
                            if(video.isInPlayingState()){
                                video.onVideoPause();
                            }
                        }
                    }else{
                        int videoBottomYInRecyclerView = itemView.getTop() + video.getBottom(); // video view 在 recycler vie 中的 bot
                        int excess = videoBottomYInRecyclerView - recyclerView.getHeight(); // video view 在 recycler view 中超出部分
                        //  如果video view 整个都在recycler view  里面或者 video 有一部分已经超出了 recycler view 下面一部分,但是超出部分不足 video view 高度的三分之一
                        if (excess < getPlayOrStopThreshold(videoHeight)) {
                            if(video.isInInPause()){
                                video.onVideoResume(false);
                            }else if(!video.isInPlayingState()){
                                video.startPrepare();
                            }
                            break;
                        }else{
                            if(video.isInPlayingState()){
                                video.onVideoPause();
                            }
                        }
                    }
                }
    
    
            }
        }
        /**
         * 返回 video view 上边 或者 下边 垂直方向上在屏幕之外的距离,如果大于这个距离 就停止播放,小于这个距离就自动播放
         * 默认是高度的 1/3,   返回 0 表示,只有整个Video View 都在屏幕上可见是才播放。
         * @param videoHeight
         * @return
         */
        public int getPlayOrStopThreshold(int videoHeight){
            return 0;
        }
    
    
        // 看一下是否有满足自动播放的 video
        public static void playIfNeed(final RecyclerView recyclerView){
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    recyclerView.smoothScrollBy(0,1);
                }
            });
        }
    }
    
    

    创建MkAutoPlayVideoHolder (如果这个holder 实现了这个接口,意味着这个holder 对应的item 里面的视频会自动播放)

    public interface MkAutoPlayVideoHolder {
        WDSVideo getVideoVIew();
    }
    

    创建一个清空视频管理器:

    
    public class MkEmptyVideo extends WDSVideo {
    
        public MkEmptyVideo(Context context, Boolean fullFlag) {
            super(context, fullFlag);
        }
        public MkEmptyVideo(Context context) {
            super(context);
        }
        public MkEmptyVideo(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public int getLayoutId() {
            return R.layout.lib_video_empty_layout;
        }
    
       //触摸上的逻辑
        @Override
        protected void touchSurfaceMoveFullLogic(float absDeltaX, float absDeltaY) {
            super.touchSurfaceMoveFullLogic(absDeltaX, absDeltaY);
            //不给触摸快进,如果需要,屏蔽下方代码即可
            mChangePosition = false;
    
            //不给触摸音量,如果需要,屏蔽下方代码即可
            mChangeVolume = false;
    
            //不给触摸亮度,如果需要,屏蔽下方代码即可
            mBrightness = false;
        }
    
        @Override
        protected void touchDoubleUp() {
            super.touchDoubleUp();
            //不需要双击暂停
        }
    }
    

    那么我们如何使用这个vidoe 呢?
    首先是布局:

     <com.wds.libvideo.WDSVideo
            android:id="@+id/playerVideo"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:layout_constraintDimensionRatio="w,1:1.77"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    

    在viewHolder 视频器中使用:

        private   class VideoHolder extends NewsHolder{
    
            private ItemNewsVideoBinding binding;
            private GSYVideoOptionBuilder gsyVideoOptionBuilder;
            public VideoHolder(@NonNull View itemView) {
                super(itemView);
                binding = ItemNewsVideoBinding.bind(itemView);
                gsyVideoOptionBuilder=new GSYVideoOptionBuilder();
            }
    
            @Override
            public void bindData(News news) {
                binding.title.setText(news.getTheme());
                // GlideApp.with(itemView).load(news.getImageUrl()).into(binding.cover);
                binding.label.setText(news.getColumn_name());
                gsyVideoOptionBuilder
                        .setIsTouchWiget(false)
                        //.setThumbImageView(imageView)
                        .setUrl(news.getVideo_url())
                        .setCacheWithPlay(false)
                        .setRotateViewAuto(true)
                        .setLockLand(true)
                        .setPlayTag(mPlayTag)
                        .setShowFullAnimation(true)
                        .setNeedShowWifiTip(false)
                        .setNeedLockFull(true)
                        .setVideoAllCallBack(new GSYSampleCallBack() {
                            @Override
                            public void onPrepared(String url, Object... objects) {
                                super.onPrepared(url, objects);
                                if (!binding.playerVideo.isIfCurrentIsFullscreen()) {
                                    //静音
                                    GSYVideoManager.instance().setNeedMute(true);
                                }
    
                            }
    
                            @Override
                            public void onQuitFullscreen(String url, Object... objects) {
                                super.onQuitFullscreen(url, objects);
                                //全屏不静音
                                GSYVideoManager.instance().setNeedMute(true);
                            }
    
                            @Override
                            public void onEnterFullscreen(String url, Object... objects) {
                                super.onEnterFullscreen(url, objects);
                                GSYVideoManager.instance().setNeedMute(false);
                                binding.playerVideo.getCurrentPlayer().getTitleTextView().setText((String)objects[0]);
                            }
                        }).build(binding.playerVideo);
                //增加title
                //binding.playerVideo.getTitleTextView().setVisibility(View.VISIBLE);
    
                //设置返回键
                binding.playerVideo.getBackButton().setVisibility(View.VISIBLE);
                GlideApp.with(itemView).load(news.getImageUrl()).into( binding.playerVideo.getCoverView());
                //设置全屏按键功能
                binding.playerVideo.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        resolveFullBtn(binding.playerVideo);
                    }
                });
    
            }
    

    相关文章

      网友评论

        本文标题:视频

        本文链接:https://www.haomeiwen.com/subject/ibfoektx.html