在研究GSYVideoPlayer框架源码之前,先来探究一下如果如何使用框架提供的、基础的视频播器放组件类GSYVideoPlayer.java,通过层层封装继承,可以看出它也是继承自FrameLayout这个帧布局管理类,B站的IjkVideoPlayer视频播放器组件的定义也是继承自它。
打开GSYVideoPlayer-master(官网实例demo)通过查看标准的“简单直接播放”按钮对应的标准播放器组件StandardGSYVideoPlayer.java类,可看到下图的继承关系图。
下面,为了便于分析播放器组件!为了便于分析播放器组件!为了便于分析播放器组件!重要的事情说三遍。我们的任务就是按照自定义组件的步骤流程,通过继承框架提供的视频播器放组件父类(GSYVideoPlayer.java),来抄一份StandardGSYVideoPlayer.java源码样例,我们对这个源码样例StandardGSYVideoPlayer.java进行分型,为了和这个播放器组件区分,我们创建一个空类叫MyStandardGSYVideoPlayer.java,通过Alt+Enter组合键可以查看继承GSYVideoPlayer父类所必须实现的抽象方法,也是在下面这张图中所示的:
MyStandardGSYVideoPlayer类如下:
由于这个类是一个自定义的播放器组件类,继承了 GSYVideoPlayer.java类,所以需要重写、实现父类GSYVideoPlayer中定义的一些抽象方法和接口方法,以及定义组件所必须提供的3个构造方法:
-
/* @author: LQS
-
* @date: 2020/12/15
-
* @description:
-
*/
-
class MyStandardGSYVideoPlayer extends GSYVideoPlayer {
-
-
/**
-
* 自定义组件的3个构造方法
-
* @param context
-
*/
-
public MyStandardGSYVideoPlayer(Context context) {
-
super(context);
-
}
-
-
public MyStandardGSYVideoPlayer(Context context, AttributeSet attrs) {
-
super(context, attrs);
-
}
-
-
public MyStandardGSYVideoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
-
super(context, attrs, defStyleAttr);
-
}
-
-
-
}
可以看出主要的方法都是来自GSYVideoView和GSYVideoControlView,这两个类。
下面就是从源码样例类StandardGSYVideoPlayer.java类中复制代码到我们MyStandardGSYVideoPlayer.java类中去分析了。
首先第一大部分就是关于视频播放组件关键的变量:
-
//亮度dialog
-
protected Dialog mBrightnessDialog;
-
-
//音量dialog
-
protected Dialog mVolumeDialog;
-
-
//触摸进度dialog
-
protected Dialog mProgressDialog;
-
-
//触摸进度条的progress
-
protected ProgressBar mDialogProgressBar;
-
-
//音量进度条的progress
-
protected ProgressBar mDialogVolumeProgressBar;
-
-
//亮度文本
-
protected TextView mBrightnessDialogTv;
-
-
//触摸移动显示文本
-
protected TextView mDialogSeekTime;
-
-
//触摸移动显示全部时间
-
protected TextView mDialogTotalTime;
-
-
//触摸移动方向icon
-
protected ImageView mDialogIcon;
-
-
protected Drawable mBottomProgressDrawable;
-
-
protected Drawable mBottomShowProgressDrawable;
-
-
protected Drawable mBottomShowProgressThumbDrawable;
-
-
protected Drawable mVolumeProgressDrawable;
-
-
protected Drawable mDialogProgressBarDrawable;
-
-
protected
int mDialogProgressHighLightColor = -
11;
-
-
protected
int mDialogProgressNormalColor = -
11;
关键的都注释了。
第二大部分就是关于视频播放组件布局初初始化方法:
这部分也没事么好解释的。getLayoutId()是覆写父类GSYVideoView.java的用于指定初始化布局资源id的方法。其他的方法也是用于指定资源id的方法。
-
/**
-
* 继承后重写可替换为你需要的布局
-
* @return
-
*/
-
@Override
-
public int getLayoutId() {
-
return R.layout.video_layout_standard;
-
}
-
-
/**
-
* 触摸进度dialog对话框的layoutId
-
* 屏幕中心区域:触摸快进、快退进度条
-
* 继承后重写可返回自定义
-
* 有自定义的实现逻辑可重载showProgressDialog方法
-
*/
-
protected int getProgressDialogLayoutId() {
-
return com.shuyu.gsyvideoplayer.R.layout.video_progress_dialog;
-
}
-
-
/**
-
* 触摸进度dialog对话框的进度条ProgressBar的id
-
* 屏幕中心区域:触摸快进、快退进度条
-
* 继承后重写可返回自定义,如果没有可返回空
-
* 有自定义的实现逻辑可重载showProgressDialog方法
-
*/
-
protected int getProgressDialogProgressId() {
-
return com.shuyu.gsyvideoplayer.R.id.duration_progressbar;
-
}
-
-
/**
-
* 触摸进度dialog对话框的当前时间文本
-
* 屏幕中心区域:触摸快进、快退进度条
-
* 继承后重写可返回自定义,如果没有可返回空
-
* 有自定义的实现逻辑可重载showProgressDialog方法
-
*/
-
protected int getProgressDialogCurrentDurationTextId() {
-
return com.shuyu.gsyvideoplayer.R.id.tv_current;
-
}
-
-
/**
-
* 触摸进度dialog对话框的视频总时长时间文本
-
* 屏幕中心区域:触摸快进、快退进度条
-
* 继承后重写可返回自定义,如果没有可返回空
-
* 有自定义的实现逻辑可重载showProgressDialog方法
-
*/
-
protected int getProgressDialogAllDurationTextId() {
-
return com.shuyu.gsyvideoplayer.R.id.tv_duration;
-
}
-
-
/**
-
* 触摸进度dialog对话框的快进、快退图片id
-
* 屏幕中心区域:触摸快进、快退进度条
-
* 继承后重写可返回自定义,如果没有可返回空
-
* 有自定义的实现逻辑可重载showProgressDialog方法
-
*/
-
protected int getProgressDialogImageId() {
-
return com.shuyu.gsyvideoplayer.R.id.duration_image_tip;
-
}
-
-
/**
-
* 音量dialog的layoutId
-
* 屏幕左侧上下滑动控制音量的对话框布局
-
* 继承后重写可返回自定义
-
* 有自定义的实现逻辑可重载showVolumeDialog方法
-
*/
-
protected int getVolumeLayoutId() {
-
return com.shuyu.gsyvideoplayer.R.layout.video_volume_dialog;
-
}
-
-
/**
-
* 音量dialog对话框的ProgressBar百分比进度条 id
-
* 屏幕左侧上下滑动控制音量的对话框布局
-
* 继承后重写可返回自定义,如果没有可返回空
-
* 有自定义的实现逻辑可重载showVolumeDialog方法
-
*/
-
protected int getVolumeProgressId() {
-
return com.shuyu.gsyvideoplayer.R.id.volume_progressbar;
-
}
-
-
-
/**
-
* 亮度dialog对话框的layoutId
-
* 屏幕右侧上下滑动控制亮度的对话框布局
-
* 继承后重写可返回自定义
-
* 有自定义的实现逻辑可重载showBrightnessDialog方法
-
*/
-
protected int getBrightnessLayoutId() {
-
return com.shuyu.gsyvideoplayer.R.layout.video_brightness;
-
}
-
-
/**
-
* 亮度dialog的百分比text id
-
* 屏幕右侧上下滑动控制亮度的对话框布局
-
* 继承后重写可返回自定义,如果没有可返回空
-
* 有自定义的实现逻辑可重载showBrightnessDialog方法
-
*/
-
protected int getBrightnessTextId() {
-
return com.shuyu.gsyvideoplayer.R.id.app_video_brightness;
-
}
第三大部分就是关于视频播放组件根据播放状态显示/隐藏UI按钮方法:
这里需要给出示意图说明一下播放组件的屏幕组成结构:①顶部返回按钮和视频标题;②中部的播放/暂停按钮、触摸滑动时的快进/快退图标和进度条;③底部的当前播放点时间文本/视频总时长和进度条;④以及最下面的视频预加载进度条;
这里面会有一个逻辑当点击屏幕时所有的UI按钮、图标、文本信息和都会显示,2.5秒之内再次点击屏幕,所有的UI按钮、图标、文本信息会立即隐藏,若2.5秒之后不点击屏幕也会自动隐藏(这个后面会说),代码如下:
-
-
-
/********************************根据播放状态控制UI显示的方法*********************************************/
-
@Override
-
protected void changeUiToPlayingShow() {
-
Debuger.printfLog(
"changeUiToPlayingShow");
-
//顶部返回按钮和标题根布局
-
setViewShowState(mTopContainer, VISIBLE);
-
//底部播放时长文本和进度条、全屏按钮的根布局
-
setViewShowState(mBottomContainer, VISIBLE);
-
//屏幕中间区域开始、暂停按钮
-
setViewShowState(mStartButton, VISIBLE);
-
//屏幕中心区域,和播放/暂停按钮同一位置处的Loading加载中图标,它是一个自定义的组件moe.codeest.enviews.ENDownloadView
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
//视频封面的父布局,这个即使一个空的相对布局
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
//底部进度调,应该是缓存进度条
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, (mIfCurrentIsFullscreen && mNeedLockFull) ? VISIBLE : GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
updateStartImage();
-
}
-
-
/*下面的所有方法注释不再给出,因为和上面播放时控制的变量都是一样的,只不过显示/隐藏值不同罢了
-
*/
-
-
/**
-
* 点击触摸显示和隐藏逻辑
-
* 在控制播放按钮自动隐藏前,通过点击屏幕使得控制播放按钮隐藏、显示的逻辑
-
*/
-
@Override
-
protected void onClickUiToggle() {
-
if (mIfCurrentIsFullscreen && mLockCurScreen && mNeedLockFull) {
-
setViewShowState(mLockScreen, VISIBLE);
-
return;
-
}
-
if (mCurrentState == CURRENT_STATE_PREPAREING) {
-
if (mBottomContainer !=
null) {
-
if (mBottomContainer.getVisibility() == View.VISIBLE) {
-
changeUiToPrepareingClear();
-
}
else {
-
changeUiToPreparingShow();
-
}
-
}
-
}
else
if (mCurrentState == CURRENT_STATE_PLAYING) {
-
if (mBottomContainer !=
null) {
-
if (mBottomContainer.getVisibility() == View.VISIBLE) {
-
changeUiToPlayingClear();
-
}
else {
-
changeUiToPlayingShow();
-
}
-
}
-
}
else
if (mCurrentState == CURRENT_STATE_PAUSE) {
-
if (mBottomContainer !=
null) {
-
if (mBottomContainer.getVisibility() == View.VISIBLE) {
-
changeUiToPauseClear();
-
}
else {
-
changeUiToPauseShow();
-
}
-
}
-
}
else
if (mCurrentState == CURRENT_STATE_AUTO_COMPLETE) {
-
if (mBottomContainer !=
null) {
-
if (mBottomContainer.getVisibility() == View.VISIBLE) {
-
changeUiToCompleteClear();
-
}
else {
-
changeUiToCompleteShow();
-
}
-
}
-
}
else
if (mCurrentState == CURRENT_STATE_PLAYING_BUFFERING_START) {
-
if (mBottomContainer !=
null) {
-
if (mBottomContainer.getVisibility() == View.VISIBLE) {
-
changeUiToPlayingBufferingClear();
-
}
else {
-
changeUiToPlayingBufferingShow();
-
}
-
}
-
}
-
}
-
-
@Override
-
protected void changeUiToNormal() {
-
Debuger.printfLog(
"changeUiToNormal");
-
//设置组件显示、隐藏:view.setVisibility(visibility);
-
setViewShowState(mTopContainer, VISIBLE);
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mStartButton, VISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, VISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, (mIfCurrentIsFullscreen && mNeedLockFull) ? VISIBLE : GONE);
-
-
updateStartImage();
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
}
-
-
@Override
-
protected void changeUiToPreparingShow() {
-
Debuger.printfLog(
"changeUiToPreparingShow");
-
-
setViewShowState(mTopContainer, VISIBLE);
-
setViewShowState(mBottomContainer, VISIBLE);
-
setViewShowState(mStartButton, INVISIBLE);
-
setViewShowState(mLoadingProgressBar, VISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
ENDownloadView enDownloadView = (ENDownloadView) mLoadingProgressBar;
-
if (enDownloadView.getCurrentState() == ENDownloadView.STATE_PRE) {
-
((ENDownloadView) mLoadingProgressBar).start();
-
}
-
}
-
}
-
-
@Override
-
protected void changeUiToPauseShow() {
-
Debuger.printfLog(
"changeUiToPauseShow");
-
-
setViewShowState(mTopContainer, VISIBLE);
-
setViewShowState(mBottomContainer, VISIBLE);
-
setViewShowState(mStartButton, VISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, (mIfCurrentIsFullscreen && mNeedLockFull) ? VISIBLE : GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
updateStartImage();
-
updatePauseCover();
-
}
-
-
@Override
-
protected void changeUiToCompleteShow() {
-
Debuger.printfLog(
"changeUiToCompleteShow");
-
-
setViewShowState(mTopContainer, VISIBLE);
-
setViewShowState(mBottomContainer, VISIBLE);
-
setViewShowState(mStartButton, VISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, VISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, (mIfCurrentIsFullscreen && mNeedLockFull) ? VISIBLE : GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
updateStartImage();
-
}
-
-
@Override
-
protected void changeUiToError() {
-
Debuger.printfLog(
"changeUiToError");
-
-
setViewShowState(mTopContainer, INVISIBLE);
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mStartButton, VISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, (mIfCurrentIsFullscreen && mNeedLockFull) ? VISIBLE : GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
updateStartImage();
-
}
-
-
@Override
-
protected void changeUiToPlayingBufferingShow() {
-
Debuger.printfLog(
"changeUiToPlayingBufferingShow");
-
-
setViewShowState(mTopContainer, VISIBLE);
-
setViewShowState(mBottomContainer, VISIBLE);
-
setViewShowState(mStartButton, INVISIBLE);
-
setViewShowState(mLoadingProgressBar, VISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
ENDownloadView enDownloadView = (ENDownloadView) mLoadingProgressBar;
-
if (enDownloadView.getCurrentState() == ENDownloadView.STATE_PRE) {
-
((ENDownloadView) mLoadingProgressBar).start();
-
}
-
}
-
}
-
-
/********************************根据播放状态控制UI隐藏的方法*********************************************/
-
-
/**
-
* 隐藏所有关于播放的信息:顶部返回按钮和标题栏,中部的开始/暂停/加载中按钮图标,底部的播放时长文本、进度条和全屏按钮
-
*/
-
@Override
-
protected void hideAllWidget() {
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mTopContainer, INVISIBLE);
-
setViewShowState(mBottomProgressBar, VISIBLE);
-
setViewShowState(mStartButton, INVISIBLE);
-
}
-
-
protected void changeUiToPrepareingClear() {
-
Debuger.printfLog(
"changeUiToPrepareingClear");
-
-
setViewShowState(mTopContainer, INVISIBLE);
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mStartButton, INVISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
}
-
-
protected void changeUiToPlayingClear() {
-
Debuger.printfLog(
"changeUiToPlayingClear");
-
changeUiToClear();
-
setViewShowState(mBottomProgressBar, VISIBLE);
-
}
-
-
protected void changeUiToPauseClear() {
-
Debuger.printfLog(
"changeUiToPauseClear");
-
changeUiToClear();
-
setViewShowState(mBottomProgressBar, VISIBLE);
-
updatePauseCover();
-
}
-
-
protected void changeUiToPlayingBufferingClear() {
-
Debuger.printfLog(
"changeUiToPlayingBufferingClear");
-
-
setViewShowState(mTopContainer, INVISIBLE);
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mStartButton, INVISIBLE);
-
setViewShowState(mLoadingProgressBar, VISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, VISIBLE);
-
setViewShowState(mLockScreen, GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
ENDownloadView enDownloadView = (ENDownloadView) mLoadingProgressBar;
-
if (enDownloadView.getCurrentState() == ENDownloadView.STATE_PRE) {
-
((ENDownloadView) mLoadingProgressBar).start();
-
}
-
}
-
updateStartImage();
-
}
-
-
protected void changeUiToClear() {
-
Debuger.printfLog(
"changeUiToClear");
-
-
setViewShowState(mTopContainer, INVISIBLE);
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mStartButton, INVISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, INVISIBLE);
-
setViewShowState(mBottomProgressBar, INVISIBLE);
-
setViewShowState(mLockScreen, GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
}
-
-
protected void changeUiToCompleteClear() {
-
Debuger.printfLog(
"changeUiToCompleteClear");
-
-
setViewShowState(mTopContainer, INVISIBLE);
-
setViewShowState(mBottomContainer, INVISIBLE);
-
setViewShowState(mStartButton, VISIBLE);
-
setViewShowState(mLoadingProgressBar, INVISIBLE);
-
setViewShowState(mThumbImageViewLayout, VISIBLE);
-
setViewShowState(mBottomProgressBar, VISIBLE);
-
setViewShowState(mLockScreen, (mIfCurrentIsFullscreen && mNeedLockFull) ? VISIBLE : GONE);
-
-
if (mLoadingProgressBar
instanceof ENDownloadView) {
-
((ENDownloadView) mLoadingProgressBar).reset();
-
}
-
updateStartImage();
-
}
-
-
/**
-
* 根据播放状态设置对应的播放、暂停、出错状态
-
*/
-
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(com.shuyu.gsyvideoplayer.R.drawable.video_click_pause_selector);
-
}
else
if (mCurrentState == CURRENT_STATE_ERROR) {
-
imageView.setImageResource(com.shuyu.gsyvideoplayer.R.drawable.video_click_error_selector);
-
}
else {
-
imageView.setImageResource(com.shuyu.gsyvideoplayer.R.drawable.video_click_play_selector);
-
}
-
}
-
}
第四大部分就是关于视频播放组件如果有自定义Drawable时对其初始化设置的:
-
/**
-
* 正常小屏时,如果有自定义Drawable,则初始化设置这些Drawable
-
*/
-
@Override
-
protected void init(Context context) {
-
super.init(context);
-
-
//增加自定义ui
-
if (mBottomProgressDrawable !=
null) {
-
mBottomProgressBar.setProgressDrawable(mBottomProgressDrawable);
-
}
-
-
if (mBottomShowProgressDrawable !=
null) {
-
mProgressBar.setProgressDrawable(mBottomProgressDrawable);
-
}
-
-
if (mBottomShowProgressThumbDrawable !=
null) {
-
mProgressBar.setThumb(mBottomShowProgressThumbDrawable);
-
}
-
-
}
-
-
/**
-
* 全屏的UI逻辑:指的是如果在小屏-全屏-小屏之间切换时,有自定义Drawable,则将几个地方的样式也设置到全屏
-
*/
-
private void initFullUI(MyStandardGSYVideoPlayer myStandardGSYVideoPlayer) {
-
-
if (mBottomProgressDrawable !=
null) {
-
myStandardGSYVideoPlayer.setBottomProgressBarDrawable(mBottomProgressDrawable);
-
}
-
-
if (mBottomShowProgressDrawable !=
null && mBottomShowProgressThumbDrawable !=
null) {
-
myStandardGSYVideoPlayer.setBottomShowProgressBarDrawable(mBottomShowProgressDrawable,
-
mBottomShowProgressThumbDrawable);
-
}
-
-
if (mVolumeProgressDrawable !=
null) {
-
myStandardGSYVideoPlayer.setDialogVolumeProgressBar(mVolumeProgressDrawable);
-
}
-
-
if (mDialogProgressBarDrawable !=
null) {
-
myStandardGSYVideoPlayer.setDialogProgressBar(mDialogProgressBarDrawable);
-
}
-
-
if (mDialogProgressHighLightColor >=
0 && mDialogProgressNormalColor >=
0) {
-
myStandardGSYVideoPlayer.setDialogProgressColor(mDialogProgressHighLightColor, mDialogProgressNormalColor);
-
}
-
}
-
-
/**
-
* 底部进度条-弹出的
-
*/
-
public void setBottomShowProgressBarDrawable(Drawable drawable, Drawable thumb) {
-
mBottomShowProgressDrawable = drawable;
-
mBottomShowProgressThumbDrawable = thumb;
-
if (mProgressBar !=
null) {
-
mProgressBar.setProgressDrawable(drawable);
-
mProgressBar.setThumb(thumb);
-
}
-
}
-
-
/**
-
* 底部进度条-非弹出
-
*/
-
public void setBottomProgressBarDrawable(Drawable drawable) {
-
mBottomProgressDrawable = drawable;
-
if (mBottomProgressBar !=
null) {
-
mBottomProgressBar.setProgressDrawable(drawable);
-
}
-
}
-
-
/**
-
* 声音进度条
-
*/
-
public void setDialogVolumeProgressBar(Drawable drawable) {
-
mVolumeProgressDrawable = drawable;
-
}
-
-
-
/**
-
* 中间进度条
-
*/
-
public void setDialogProgressBar(Drawable drawable) {
-
mDialogProgressBarDrawable = drawable;
-
}
-
-
/**
-
* 中间进度条字体颜色
-
*/
-
public void setDialogProgressColor(int highLightColor, int normalColor) {
-
mDialogProgressHighLightColor = highLightColor;
-
mDialogProgressNormalColor = normalColor;
-
}
第五部分亮度Dialog、音量Dialog、快进快退Dialog显示隐藏及数值变化逻辑的控制:
效果图如下:
代码如下:
-
-
-
/************************************* 亮度Dialog、音量Dialog、快进快退Dialog显示隐藏及数值变化逻辑的控制****************************************/
-
/**
-
* 显示wifi确定框,如需要自定义继承重写即可
-
*/
-
@Override
-
protected void showWifiDialog() {
-
if (!NetworkUtils.isAvailable(mContext)) {
-
//Toast.makeText(mContext, getResources().getString(R.string.no_net), Toast.LENGTH_LONG).show();
-
startPlayLogic();
-
return;
-
}
-
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivityContext());
-
builder.setMessage(getResources().getString(R.string.tips_not_wifi));
-
builder.setPositiveButton(getResources().getString(R.string.tips_not_wifi_confirm),
new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
dialog.dismiss();
-
startPlayLogic();
-
}
-
});
-
builder.setNegativeButton(getResources().getString(R.string.tips_not_wifi_cancel),
new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
dialog.dismiss();
-
}
-
});
-
builder.create().show();
-
}
-
-
/**
-
* 触摸显示滑动进度dialog,如需要自定义继承重写即可,记得重写dismissProgressDialog
-
* 滑动快进、快退进度条、当前播放时间文本、总时长文本
-
* 在protected void touchSurfaceMove(float deltaX, float deltaY, float y)中调用
-
*/
-
@Override
-
@SuppressWarnings("ResourceType")
-
protected void showProgressDialog(float deltaX, String seekTime, int seekTimePosition, String totalTime, int totalTimeDuration) {
-
if (mProgressDialog ==
null) {
-
View localView = LayoutInflater.from(getActivityContext()).inflate(getProgressDialogLayoutId(),
null);
-
//ProgressBar 滑动进度条
-
if (localView.findViewById(getProgressDialogProgressId())
instanceof ProgressBar) {
-
mDialogProgressBar = ((ProgressBar) localView.findViewById(getProgressDialogProgressId()));
-
if (mDialogProgressBarDrawable !=
null) {
-
mDialogProgressBar.setProgressDrawable(mDialogProgressBarDrawable);
-
}
-
}
-
//当前视频播放时间文本
-
if (localView.findViewById(getProgressDialogCurrentDurationTextId())
instanceof TextView) {
-
mDialogSeekTime = ((TextView) localView.findViewById(getProgressDialogCurrentDurationTextId()));
-
}
-
//视频总时长文本
-
if (localView.findViewById(getProgressDialogAllDurationTextId())
instanceof TextView) {
-
mDialogTotalTime = ((TextView) localView.findViewById(getProgressDialogAllDurationTextId()));
-
}
-
if (localView.findViewById(getProgressDialogImageId())
instanceof ImageView) {
-
mDialogIcon = ((ImageView) localView.findViewById(getProgressDialogImageId()));
-
}
-
//初始化一个带样式的对话框
-
mProgressDialog =
new Dialog(getActivityContext(), R.style.video_style_dialog_progress);
-
mProgressDialog.setContentView(localView);
-
mProgressDialog.getWindow().addFlags(Window.FEATURE_ACTION_BAR);
-
mProgressDialog.getWindow().addFlags(
32);
-
mProgressDialog.getWindow().addFlags(
16);
-
mProgressDialog.getWindow().setLayout(getWidth(), getHeight());
-
if (mDialogProgressNormalColor != -
11 && mDialogTotalTime !=
null) {
-
mDialogTotalTime.setTextColor(mDialogProgressNormalColor);
-
}
-
if (mDialogProgressHighLightColor != -
11 && mDialogSeekTime !=
null) {
-
mDialogSeekTime.setTextColor(mDialogProgressHighLightColor);
-
}
-
WindowManager.LayoutParams localLayoutParams = mProgressDialog.getWindow().getAttributes();
-
localLayoutParams.gravity = Gravity.TOP;
-
localLayoutParams.width = getWidth();
-
localLayoutParams.height = getHeight();
-
int location[] =
new
int[
2];
-
//获取控件在当前屏幕中的位置
-
getLocationOnScreen(location);
-
localLayoutParams.x = location[
0];
-
localLayoutParams.y = location[
1];
-
mProgressDialog.getWindow().setAttributes(localLayoutParams);
-
}
-
if (!mProgressDialog.isShowing()) {
-
mProgressDialog.show();
-
}
-
if (mDialogSeekTime !=
null) {
-
mDialogSeekTime.setText(seekTime);
-
}
-
if (mDialogTotalTime !=
null) {
-
mDialogTotalTime.setText(
" / " + totalTime);
-
}
-
if (totalTimeDuration >
0)
-
if (mDialogProgressBar !=
null) {
-
mDialogProgressBar.setProgress(seekTimePosition *
100 / totalTimeDuration);
-
}
-
if (deltaX >
0) {
-
if (mDialogIcon !=
null) {
-
mDialogIcon.setBackgroundResource(R.drawable.video_forward_icon);
-
}
-
}
else {
-
if (mDialogIcon !=
null) {
-
mDialogIcon.setBackgroundResource(R.drawable.video_backward_icon);
-
}
-
}
-
-
}
-
-
@Override
-
protected void dismissProgressDialog() {
-
if (mProgressDialog !=
null) {
-
mProgressDialog.dismiss();
-
mProgressDialog =
null;
-
}
-
}
-
-
/**
-
* 触摸音量dialog,如需要自定义继承重写即可,记得重写dismissVolumeDialog
-
*/
-
@Override
-
protected void showVolumeDialog(float deltaY, int volumePercent) {
-
if (mVolumeDialog ==
null) {
-
View localView = LayoutInflater.from(getActivityContext()).inflate(getVolumeLayoutId(),
null);
-
if (localView.findViewById(getVolumeProgressId())
instanceof ProgressBar) {
-
mDialogVolumeProgressBar = ((ProgressBar) localView.findViewById(getVolumeProgressId()));
-
if (mVolumeProgressDrawable !=
null && mDialogVolumeProgressBar !=
null) {
-
mDialogVolumeProgressBar.setProgressDrawable(mVolumeProgressDrawable);
-
}
-
}
-
mVolumeDialog =
new Dialog(getActivityContext(), R.style.video_style_dialog_progress);
-
mVolumeDialog.setContentView(localView);
-
mVolumeDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
-
mVolumeDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
-
mVolumeDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
-
mVolumeDialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-
WindowManager.LayoutParams localLayoutParams = mVolumeDialog.getWindow().getAttributes();
-
localLayoutParams.gravity = Gravity.TOP | Gravity.START;
-
localLayoutParams.width = getWidth();
-
localLayoutParams.height = getHeight();
-
int location[] =
new
int[
2];
-
getLocationOnScreen(location);
-
localLayoutParams.x = location[
0];
-
localLayoutParams.y = location[
1];
-
mVolumeDialog.getWindow().setAttributes(localLayoutParams);
-
}
-
if (!mVolumeDialog.isShowing()) {
-
mVolumeDialog.show();
-
}
-
if (mDialogVolumeProgressBar !=
null) {
-
mDialogVolumeProgressBar.setProgress(volumePercent);
-
}
-
}
-
-
@Override
-
protected void dismissVolumeDialog() {
-
if (mVolumeDialog !=
null) {
-
mVolumeDialog.dismiss();
-
mVolumeDialog =
null;
-
}
-
}
-
-
-
/**
-
* 触摸亮度dialog,如需要自定义继承重写即可,记得重写dismissBrightnessDialog
-
*/
-
@Override
-
protected void showBrightnessDialog(float percent) {
-
if (mBrightnessDialog ==
null) {
-
View localView = LayoutInflater.from(getActivityContext()).inflate(getBrightnessLayoutId(),
null);
-
if (localView.findViewById(getBrightnessTextId())
instanceof TextView) {
-
mBrightnessDialogTv = (TextView) localView.findViewById(getBrightnessTextId());
-
}
-
mBrightnessDialog =
new Dialog(getActivityContext(), R.style.video_style_dialog_progress);
-
mBrightnessDialog.setContentView(localView);
-
mBrightnessDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
-
mBrightnessDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
-
mBrightnessDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
-
mBrightnessDialog.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
-
mBrightnessDialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-
WindowManager.LayoutParams localLayoutParams = mBrightnessDialog.getWindow().getAttributes();
-
localLayoutParams.gravity = Gravity.TOP | Gravity.END;
-
localLayoutParams.width = getWidth();
-
localLayoutParams.height = getHeight();
-
int location[] =
new
int[
2];
-
getLocationOnScreen(location);
-
localLayoutParams.x = location[
0];
-
localLayoutParams.y = location[
1];
-
mBrightnessDialog.getWindow().setAttributes(localLayoutParams);
-
}
-
if (!mBrightnessDialog.isShowing()) {
-
mBrightnessDialog.show();
-
}
-
if (mBrightnessDialogTv !=
null)
-
mBrightnessDialogTv.setText((
int) (percent *
100) +
"%");
-
}
-
-
-
@Override
-
protected void dismissBrightnessDialog() {
-
if (mBrightnessDialog !=
null) {
-
mBrightnessDialog.dismiss();
-
mBrightnessDialog =
null;
-
}
-
}
-
-
@Override
-
protected void onDetachedFromWindow() {
-
super.onDetachedFromWindow();
-
dismissVolumeDialog();
-
dismissBrightnessDialog();
-
}
第六部分正常小屏--全屏--小屏进行切换时,需要将当前正在播放的信息、样式复制给将要使用的屏幕模式
这里只是参数的拷贝,没有涉及到全屏-小屏切换按钮的逻辑,在 GSYVideoPlayer播放器框架使用、播放组件源码探究(三)中补充讲解。
-
-
/**
-
* 全屏-小屏-全屏相互切换时,将当前播放时间点、视频时长、进度条百分比进度拷贝给播放器对象
-
* @param from
-
* @param to
-
*/
-
@Override
-
protected void cloneParams(GSYBaseVideoPlayer from, GSYBaseVideoPlayer to) {
-
super.cloneParams(from, to);
-
MyStandardGSYVideoPlayer sf = (MyStandardGSYVideoPlayer) from;
-
MyStandardGSYVideoPlayer st = (MyStandardGSYVideoPlayer) to;
-
if (st.mProgressBar !=
null && sf.mProgressBar !=
null) {
-
st.mProgressBar.setProgress(sf.mProgressBar.getProgress());
-
st.mProgressBar.setSecondaryProgress(sf.mProgressBar.getSecondaryProgress());
-
}
-
if (st.mTotalTimeTextView !=
null && sf.mTotalTimeTextView !=
null) {
-
st.mTotalTimeTextView.setText(sf.mTotalTimeTextView.getText());
-
}
-
if (st.mCurrentTimeTextView !=
null && sf.mCurrentTimeTextView !=
null) {
-
st.mCurrentTimeTextView.setText(sf.mCurrentTimeTextView.getText());
-
}
-
}
-
-
/**
-
* 将自定义的效果也设置到全屏
-
*
-
* @param context
-
* @param actionBar 是否有actionBar,有的话需要隐藏
-
* @param statusBar 是否有状态bar,有的话需要隐藏
-
* @return
-
*/
-
@Override
-
public GSYBaseVideoPlayer startWindowFullscreen(Context context, boolean actionBar, boolean statusBar) {
-
GSYBaseVideoPlayer gsyBaseVideoPlayer =
super.startWindowFullscreen(context, actionBar, statusBar);
-
if (gsyBaseVideoPlayer !=
null) {
-
MyStandardGSYVideoPlayer gsyVideoPlayer = (MyStandardGSYVideoPlayer) gsyBaseVideoPlayer;
-
gsyVideoPlayer.setLockClickListener(mLockClickListener);
-
gsyVideoPlayer.setNeedLockFull(isNeedLockFull());
-
initFullUI(gsyVideoPlayer);
-
//比如你自定义了返回案件,但是因为返回按键底层已经设置了返回事件,所以你需要在这里重新增加的逻辑
-
}
-
return gsyBaseVideoPlayer;
-
}
第七部分关于截图功能:
关于截图这块是扩展功能,可暂时忽略,后面需要时再研究。
-
-
/************************************* 关于截图的 ****************************************/
-
-
/**
-
* 获取截图
-
*/
-
public void taskShotPic(GSYVideoShotListener gsyVideoShotListener) {
-
this.taskShotPic(gsyVideoShotListener,
false);
-
}
-
-
/**
-
* 获取截图
-
*
-
* @param high 是否需要高清的
-
*/
-
public void taskShotPic(GSYVideoShotListener gsyVideoShotListener, boolean high) {
-
if (getCurrentPlayer().getRenderProxy() !=
null) {
-
getCurrentPlayer().getRenderProxy().taskShotPic(gsyVideoShotListener, high);
-
}
-
}
-
-
/**
-
* 保存截图
-
*/
-
public void saveFrame(final File file, GSYVideoShotSaveListener gsyVideoShotSaveListener) {
-
saveFrame(file,
false, gsyVideoShotSaveListener);
-
}
-
-
/**
-
* 保存截图
-
*
-
* @param high 是否需要高清的
-
*/
-
public void saveFrame(final File file, final boolean high, final GSYVideoShotSaveListener gsyVideoShotSaveListener) {
-
if (getCurrentPlayer().getRenderProxy() !=
null) {
-
getCurrentPlayer().getRenderProxy().saveFrame(file, high, gsyVideoShotSaveListener);
-
}
-
}
第八部分贴出开始播放的逻辑代码,这个比较少:
-
/**
-
* 开始播放
-
*/
-
@Override
-
public void startPlayLogic() {
-
if (mVideoAllCallBack !=
null) {
-
Debuger.printfLog(
"onClickStartThumb");
-
mVideoAllCallBack.onClickStartThumb(mOriginUrl, mTitle, MyStandardGSYVideoPlayer.
this);
-
}
-
/**
-
* 父类GSYVideoControlView方法:增对列表优化,在播放前的时候才进行setup
-
* 优化内容:
-
* 设置播放URL
-
* @param url 播放url
-
* @param cacheWithPlay 是否边播边缓存
-
* @param cachePath 缓存路径,如果是M3U8或者HLS,请设置为false
-
* @param mapHeadData 头部信息
-
* @param title title
-
*/
-
prepareVideo();
-
/**
-
* 开始对视频播放组件上层的播放、暂停、播放进度条、播放时间/总时长等按钮的显示/隐藏进行控制
-
*
-
* protected int mDismissControlTime = 2500; 触摸显示后隐藏的时间:触摸显示控制按钮,2.5秒后隐藏所有控制按钮
-
* Runnable dismissControlTask = new Runnable(); 通过postDelayed()延时2.5秒后向消息队列发送一个可执行的子线程消息,去隐藏控制按钮更新界面
-
*/
-
startDismissControlViewTimer();
-
}
-
-
/**
-
* 重新开启进度查询以及控制view消失的定时任务
-
* 用于解决GSYVideoHelper中通过removeview方式做全屏切换导致的定时任务停止的问题
-
* GSYVideoControlView onDetachedFromWindow()
-
*/
-
public void restartTimerTask() {
-
startProgressTimer();
-
startDismissControlViewTimer();
-
}
好了到这里源码样例类StandardGSYVideoPlayer.java类的代码基本都分析完了 ,都在注释里,可以细细的品!
下面来说两部分,自动隐藏播放界面上层的UI按钮、图标、文本信息和通过手势滑动控制音量Dialog、进度条Dialog、屏幕亮度Dialog的逻辑,鉴于篇幅过长,将总结到第二篇。
GSYVideoPlayer播放器框架使用、播放组件源码探究(二):https://blog.csdn.net/luqingshuai_eloong/article/details/111318995
转载:https://blog.csdn.net/luqingshuai_eloong/article/details/111209282