基于VideoView自定义控制面板的视频播放器
本文实例为大家分享了VideoView原生自定义视频播放器的具体代码,供大家参考,具体内容如下
项目用到的技术点和亮点
- VideoView封装视频播放工具类
- 自定义视频控制面板
- 手势识别器的使用
1.VideoView封装视频播放工具类
视频播放这些其实都挺简单的,VideoView这个类都提供了相应方法,详细见代码代码都比较简单,不过需要注意的是要在主线程中更新视频面板的UI信息。
/******************************************************** *视频业务类 *最后修改时间:2017/9/23 *@authorzlc * *********************************************************/ packagecom.zlc.video; importandroid.app.Activity; importandroid.content.Context; importandroid.content.pm.ActivityInfo; importandroid.media.MediaPlayer; importandroid.os.Handler; importandroid.os.Looper; importandroid.os.Message; importandroid.os.PowerManager; importandroid.os.PowerManager.WakeLock; importandroid.util.Log; importandroid.view.View; importandroid.widget.ImageView; importandroid.widget.VideoView; publicclassVideoBusinessimplementsMediaPlayer.OnPreparedListener,MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener{ privateActivityactivity; privateWakeLockmWakeLock; publicVideoViewmVideoView; privateVideoControllermController; /**播放状态枚举,有三种播放状态:空闲,正在准备*/ privateenumPLAYER_STATUS{ IDLE,PREPARING,PAUSED,PREPARED,RESUMED,STOPPED } /**当前播放状态*/ publicPLAYER_STATUSmPlayerStatus=PLAYER_STATUS.IDLE; /**播放信息异步处理方法,用于更新进度*/ /**事件标志*/ privateintmLastPos; publicVideoBusiness(Activityactivity){ this.activity=activity; //保持屏幕高亮 PowerManagerpm=(PowerManager)activity.getSystemService(Context.POWER_SERVICE); mWakeLock=pm.newWakeLock(PowerManager.FULL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Test"); } //初始化视频播放器 publicvoidinitVideo(VideoViewvideoView,VideoControllercontroller,StringsourceUrl){ this.mVideoView=videoView; this.mController=controller; mController.setVideoBusiness(this); Log.e("msg","设置播放地址="+sourceUrl); mVideoView.setOnPreparedListener(this); mVideoView.setOnCompletionListener(this); mVideoView.setOnErrorListener(this); mVideoView.setVideoPath(sourceUrl);//设置播放地址 } //开始播放 publicvoidstartPlay(){ if(null!=mWakeLock&&(!mWakeLock.isHeld())){ mWakeLock.acquire(); } if(null!=mVideoView){ Log.e("msg","播放"); mVideoView.start(); mPlayerStatus=PLAYER_STATUS.PREPARING; } } /** *暂停播放 */ publicvoidpause(){ if(null!=mWakeLock){ mWakeLock.release(); } if(null!=mVideoView&&mVideoView.isPlaying()){ mVideoView.pause(); mPlayerStatus=PLAYER_STATUS.PAUSED; mLastPos=getCurrentTime(); } } /** *继续播放 */ publicvoidresume(){ if(null!=mWakeLock){ mWakeLock.acquire(); } if(null!=mVideoView){ //mVideoView.resume(); mVideoView.seekTo(mLastPos); mVideoView.start(); mPlayerStatus=PLAYER_STATUS.RESUMED; } } /** *停止播放 */ publicvoidstop(){ if(null!=mWakeLock){ mWakeLock.release(); } if(null!=mVideoView){ mLastPos=getCurrentTime(); mVideoView.stopPlayback(); mPlayerStatus=PLAYER_STATUS.STOPPED; } } /** *判断是否正在播放 *@return */ publicbooleanisPlaying(){ returnmVideoView!=null&&mVideoView.isPlaying(); } /** *是否暂停 */ publicbooleanisPause(){ returnmPlayerStatus==PLAYER_STATUS.PAUSED; } /** *释放资源 */ publicvoidrelease(){ if(null!=mWakeLock){ mWakeLock.release(); mWakeLock=null; } if(null!=mVideoView){ mVideoView.stopPlayback(); mVideoView=null; } } @Override publicvoidonCompletion(MediaPlayermediaPlayer){ Log.e("onCompletion","视频播放完了"); mController.showLong(); mController.setProgress(0); mLastPos=0; mPlayerStatus=PLAYER_STATUS.IDLE; removeUIMessage(); } @Override publicbooleanonError(MediaPlayermediaPlayer,inti,inti1){ Log.e("onError","视频播放报错了"); returnfalse; } @Override publicvoidonPrepared(MediaPlayermediaPlayer){ Log.e("onPrepared","视频准备好了"); if(mPlayerStatus!=PLAYER_STATUS.PAUSED){ inttotalTime=getTotalTime(); mController.setTotalTime(totalTime); mController.setProgress(0); mController.setMaxProgress(totalTime); mPlayerStatus=PLAYER_STATUS.PREPARED; sendUIMessage(); } } /** *进度条拖拽播放 *@paramtime */ publicvoidseekToPlay(inttime){ inttotalSecond=getTotalTime(); inttempTime=time>totalSecond?totalSecond:time; mVideoView.seekTo(tempTime); sendUIMessage(); } //视频暂停播放播放大按钮点击事件 publicvoidplayVideo(ImageViewid_btn_video_play,ImageViewimg){ if(isPlaying()){ pause(); id_btn_video_play.setVisibility(View.VISIBLE); img.setImageResource(R.drawable.video_pause); mPlayerStatus=PLAYER_STATUS.PAUSED; mUIHandler.sendEmptyMessageDelayed(UI_EVENT_UPDATE_CURRPOSITION,500); }elseif(isPause()){ resume(); id_btn_video_play.setVisibility(View.GONE); img.setImageResource(R.drawable.video_play); mPlayerStatus=PLAYER_STATUS.RESUMED; }else{ img.setImageResource(R.drawable.video_play); id_btn_video_play.setVisibility(View.GONE); startPlay(); mPlayerStatus=PLAYER_STATUS.PREPARING; } } privatebooleanisCurrentLandscape=false;//是不是横屏 //横竖屏切换按钮点击方法 publicvoidtoggleScreenDir(Viewv){ if(isCurrentLandscape){//如果当前是横屏,则切换为竖屏,然后把按钮为变为变大的图标 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); if(vinstanceofImageView){ ((ImageView)v).setImageResource(R.drawable.zuidahua_2x); } }else{//如果当前是竖屏,则切换为横屏,然后把按钮为变为变小的图标 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); if(vinstanceofImageView){ ((ImageView)v).setImageResource(R.drawable.xiaohua_2x); } } isCurrentLandscape=!isCurrentLandscape; } publicUIHandlermUIHandler=newUIHandler(Looper.getMainLooper()); publicfinalintUI_EVENT_UPDATE_CURRPOSITION=1;//更新进度信息 publicbooleanisSeekBarEnable=true; classUIHandlerextendsHandler{ publicUIHandler(LoopermainLooper){ super(mainLooper); } @Override publicvoidhandleMessage(Messagemsg){ switch(msg.what){ //更新进度及时间 caseUI_EVENT_UPDATE_CURRPOSITION: if(isSeekBarEnable){ intcurrentPosition=getCurrentTime(); StringtimeString=mController.getTimeString(currentPosition); //Log.e("handleMessage",timeString); if(isPlaying()){ mController.setProgress(currentPosition); mUIHandler.sendEmptyMessageDelayed( UI_EVENT_UPDATE_CURRPOSITION,200); } } break; } } } publicvoidsendUIMessage(){ mUIHandler.sendEmptyMessage(UI_EVENT_UPDATE_CURRPOSITION); } publicvoidremoveUIMessage(){ mUIHandler.removeMessages(UI_EVENT_UPDATE_CURRPOSITION); } //获取视频总时间 publicintgetTotalTime(){ returnmVideoView==null?0:mVideoView.getDuration(); } //获取视频当前时间 publicintgetCurrentTime(){ returnmVideoView==null?0:mVideoView.getCurrentPosition(); } }
2.手势识别器的使用
//1.创建手势识别器 progressGestureDetector=newGestureDetector(mContext,newProgressGestureListenr()); //2.复写GestureDetector.OnGestureListener的6个方法 booleanonDown(MotionEvente)//用户按下屏幕就会触发 voidonShowPress(MotionEvente)////down事件发生而move或则up还没发生前触发该事件 booleanonSingleTapUp(MotionEvente)//一次点击up事件 booleanonScroll(MotionEvente1,MotionEvente2,floatdistanceX,floatdistanceY)//在屏幕上拖动事件 voidonLongPress(MotionEvente)//长按事件 booleanonFling(MotionEvente1,MotionEvente2,floatvelocityX,floatvelocityY)//滑动手势事件 //3onTouch中拦截 @Override publicbooleanonTouch(Viewview,MotionEventevent){ returnprogressGestureDetector.onTouchEvent(event); } //4事件绑定 progressArea.setOnTouchListener(this);
3.自定义视频控制面板
代码比较简单同时代码不长都有注释需要的可以参考下大神勿喷
packagecom.zlc.video; importandroid.app.Activity; importandroid.content.Context; importandroid.media.AudioManager; importandroid.os.Handler; importandroid.os.Message; importandroid.provider.Settings; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.view.GestureDetector; importandroid.view.MotionEvent; importandroid.view.View; importandroid.view.Window; importandroid.view.WindowManager; importandroid.widget.FrameLayout; importandroid.widget.ImageView; importandroid.widget.LinearLayout; importandroid.widget.ProgressBar; importandroid.widget.RelativeLayout; importandroid.widget.SeekBar; importandroid.widget.TextView; importcom.zlc.video.utils.DensityUtil; importcom.zlc.video.utils.ScreenUtil; importjava.text.SimpleDateFormat; importjava.util.Date; publicclassVideoControllerextendsRelativeLayoutimplementsView.OnTouchListener,View.OnClickListener,SeekBar.OnSeekBarChangeListener{ privateContextmContext; privateViewmContainer; privateVideoBusinessvideoBusiness; /**表示当前视频控制面板是否展示*/ publicbooleanisShow=true; privateHandlerhideHandler=newHandler(){ @Override publicvoidhandleMessage(Messagemsg){ if(isShow){ hideController(); } } }; /**视频功能控制底边栏*/ privateLinearLayoutmMediaController; /***************手势相关*********************/ privateintGESTURE_FLAG=0;//1调节进度,2调节音量,3调节亮度 privateFrameLayoutmProgressIndicator; privateProgressBarprogressBar; /**进度相关*/ privateGestureDetectorprogressGestureDetector; privatestaticfinalintGESTURE_MODIFY_PROGRESS=1; /**音量相关*/ privatestaticfinalintGESTURE_MODIFY_VOLUME=2; privateAudioManageraudiomanager; privateintmaxVolume,currentVolume; /**亮度相关*/ privatestaticfinalintGESTURE_MODIFY_BRIGHTNESS=3; privateWindowManager.LayoutParamsbrightnessLp; privateintmaxBrightness,currentBrightness; privateLinearLayoutprogressArea; privateinttargetTime; //UI相关 privateRelativeLayoutid_rl_video_controller; privateFrameLayoutid_fl_video_play; privateFrameLayoutid_fl_video_expand; privateTextViewid_video_time; privateTextViewid_video_totaltime; privateSeekBarid_sb_progress; privateImageViewid_btn_video_play; privateImageViewid_iv_video_play; privateTextViewid_tv_video_info; publicVideoController(Contextcontext){ this(context,null); } publicVideoController(Contextcontext,AttributeSetattrs){ this(context,attrs,0); } publicVideoController(Contextcontext,AttributeSetattrs,intdefStyle){ super(context,attrs,defStyle); mContext=context; init(); initListener(); } privatevoidinit(){ //初始化音量相关 audiomanager=(AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE); maxVolume=audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);//获取系统最大音量 currentVolume=audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC);//获取当前值 //初始化亮度相关 brightnessLp=((Activity)mContext).getWindow().getAttributes(); currentBrightness=getCurrentBrightness(); maxBrightness=255;//设置最大亮度 initView(); } privatevoidinitView(){ mContainer=View.inflate(mContext,R.layout.video_controller,null); id_rl_video_controller=findView(R.id.id_rl_video_controller); mMediaController=findView(R.id.id_ll_controller); mProgressIndicator=findView(R.id.id_fl_progress_indicator); progressBar=findView(R.id.id_pb_gesture_progress); progressArea=findView(R.id.id_ll_video_gesture_progress); id_fl_video_play=findView(R.id.id_fl_video_play); id_fl_video_expand=findView(R.id.id_fl_video_expand); id_video_time=findView(R.id.id_video_time); id_video_totaltime=findView(R.id.id_video_totaltime); id_sb_progress=findView(R.id.id_sb_progress); id_btn_video_play=findView(R.id.id_btn_video_play); id_iv_video_play=findView(R.id.id_iv_video_play); id_tv_video_info=findView(R.id.id_tv_video_info); addView(mContainer); } privateTfindView(intviewId){ return(T)mContainer.findViewById(viewId); } publicvoidsetVideoBusiness(VideoBusinessvideoBusiness){ this.videoBusiness=videoBusiness; } privatevoidinitListener(){ //进度手势相关 progressGestureDetector=newGestureDetector(mContext,newProgressGestureListenr()); progressGestureDetector.setIsLongpressEnabled(true); progressArea.setLongClickable(true); progressArea.setOnTouchListener(this); mMediaController.setOnClickListener(this); id_rl_video_controller.setOnClickListener(this); id_fl_video_play.setOnClickListener(this); id_fl_video_expand.setOnClickListener(this); id_btn_video_play.setOnClickListener(this); id_sb_progress.setOnSeekBarChangeListener(this); } //状态切换 publicvoidtoggle(){ if(isShow){ hideController(); }else{ showController(); } } //隐藏底部控制栏 publicvoidhideController(){ isShow=false; mMediaController.setVisibility(View.GONE); endTimer(); } //显示底部控制栏 publicvoidshowController(){ isShow=true; mMediaController.setVisibility(View.VISIBLE); startTimer(); } privatevoidstartTimer(){ if(hideHandler!=null){ hideHandler.removeMessages(0); } hideHandler.sendEmptyMessageDelayed(0,5000); } privatevoidendTimer(){ hideHandler.removeMessages(0); } publicvoidresetTimer(){ endTimer(); startTimer(); } publicvoidshowLong(){ isShow=true; mMediaController.setVisibility(View.VISIBLE); } //设置视频总时间 publicvoidsetTotalTime(inttime){ StringtotalTime=getTimeString(time); id_video_totaltime.setText(totalTime); } //设置视频当前进度 publicvoidsetProgress(intprogress){ intmaxProgress=videoBusiness.getTotalTime(); inttempProgress=progress>maxProgress?maxProgress:progress; id_sb_progress.setProgress(tempProgress); } //是指视频总进度 publicvoidsetMaxProgress(intmaxProgress){ id_sb_progress.setMax(maxProgress); } //获取当前亮度 privateintgetCurrentBrightness(){ intcurrentBrightness=255; if(brightnessLp.screenBrightness==WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE){ //获取系统亮度 try{ currentBrightness=Settings.System.getInt(((Activity)mContext).getContentResolver(),Settings.System.SCREEN_BRIGHTNESS); }catch(Settings.SettingNotFoundExceptione){ e.printStackTrace(); } }else{ //获取当前窗口亮度 currentBrightness=(int)(brightnessLp.screenBrightness*255); } returncurrentBrightness; } @Override publicvoidonClick(Viewview){ switch(view.getId()){ caseR.id.id_ll_controller://底部控制器 showController(); break; caseR.id.id_rl_video_controller://全屏点击 toggle(); break; caseR.id.id_fl_video_play://暂停/播放 caseR.id.id_btn_video_play://暂停/播放 videoBusiness.playVideo(id_btn_video_play,id_iv_video_play); break; caseR.id.id_fl_video_expand://全屏 resetTimer(); videoBusiness.toggleScreenDir(view); break; } } @Override publicbooleanonTouch(Viewview,MotionEventevent){ getParent().requestDisallowInterceptTouchEvent(true); if(event.getAction()==MotionEvent.ACTION_UP){ mProgressIndicator.setVisibility(View.INVISIBLE); if(GESTURE_FLAG==GESTURE_MODIFY_PROGRESS){//调节进度 Log.e("进度时间","targetTime="+targetTime); videoBusiness.seekToPlay(targetTime); videoBusiness.isSeekBarEnable=true; hideController(); } GESTURE_FLAG=0;//手指离开屏幕后,重置调节音量或进度的标志 } returnprogressGestureDetector.onTouchEvent(event); } privateintcurrentPosition;//当前播放进度 privateinttotalPosition;//总播放进度 classProgressGestureListenrimplementsGestureDetector.OnGestureListener{ privatebooleanfirstScroll=false;//每次触摸屏幕后,第一次scroll的标志 privateintslop;//触发设置变动的最小距离 @Override publicbooleanonDown(MotionEvente){//用户按下屏幕就会触发 //初始数据 slop=DensityUtil.dp2px(mContext,2); currentPosition=videoBusiness.getCurrentTime(); totalPosition=videoBusiness.getTotalTime(); firstScroll=true; returnfalse; } @Override publicvoidonShowPress(MotionEvente){//down事件发生而move或则up还没发生前触发该事件 } @Override publicbooleanonSingleTapUp(MotionEvente){//一次点击up事件 toggle(); if(videoBusiness.isPlaying()){//正在播放 returnfalse; }else{//暂停或者开始播放 videoBusiness.playVideo(id_btn_video_play,id_iv_video_play); isShow=false; returntrue; } } //在屏幕上拖动事件 @Override publicbooleanonScroll(MotionEvente1,MotionEvente2,floatdistanceX,floatdistanceY){ if(firstScroll){//以触摸屏幕后第一次滑动为标准,避免在屏幕上操作切换混乱 //横向的距离变化大则调整进度,纵向的变化大则调整音量 Log.e("xxxxxxx",e1.getX()+""); Log.e("yyyyyyy",e1.getY()+""); setScroll(e1,distanceX,distanceY); } //如果每次触摸屏幕后第一次scroll是调节进度,那之后的scroll事件都处理音量进度,直到离开屏幕执行下一次操作 switch(GESTURE_FLAG){ caseGESTURE_MODIFY_PROGRESS://调节当前进度 setCurrentProgress(distanceX,distanceY,slop); break; caseGESTURE_MODIFY_VOLUME://调节当前音量 setCurrentVolume(distanceX,distanceY,slop); break; caseGESTURE_MODIFY_BRIGHTNESS://调节当前亮度 setCurrentBrightess(distanceX,distanceY,slop); break; } firstScroll=false; returnfalse; } @Override publicvoidonLongPress(MotionEvente){//长按事件 } @Override publicbooleanonFling(MotionEvente1,MotionEvente2,floatvelocityX,floatvelocityY){//滑动手势事件 returnfalse; } } //滑动事件 privatevoidsetScroll(MotionEvente1,floatdistanceX,floatdistanceY){ intscreenWidth=ScreenUtil.getScreenWidth(mContext); Log.e("屏宽",screenWidth+""); //横向的距离变化大则调整进度,纵向的变化大则调整音量 mProgressIndicator.setVisibility(View.VISIBLE); if(Math.abs(distanceX)>=Math.abs(distanceY)){//调整进度 progressBar.setVisibility(View.INVISIBLE); id_tv_video_info.setVisibility(VISIBLE); GESTURE_FLAG=GESTURE_MODIFY_PROGRESS; videoBusiness.isSeekBarEnable=false; endTimer(); showLong(); }else{//调整音量 progressBar.setVisibility(VISIBLE); id_tv_video_info.setVisibility(INVISIBLE); if(e1.getX()>screenWidth/2){//屏幕右边上下滑动调整音量 //右半屏音量 setVideoVolume(); }else{//屏幕左边上下滑动调整亮度 //左半屏亮度 setVideoBrightness(); } } } //设置当前进度 privatevoidsetCurrentProgress(floatdistanceX,floatdistanceY,floatslop){ if(Math.abs(distanceX)>Math.abs(distanceY)){//横向移动大于纵向移动 //Log.e("setCurrentProgress",distanceX+""); if(distanceX>=slop){//从右往左滑快退 mProgressIndicator.setBackgroundResource(R.drawable.kuaitui); if(currentPosition>1000){ currentPosition-=1500; } }elseif(distanceX<=-slop){//从左往右滑快进 mProgressIndicator.setBackgroundResource(R.drawable.kuaijin); if(currentPosition Math.abs(distanceX)){//纵向移动大于横向移动 if(distanceY>=slop){//上滑亮度调大,注意横屏时的坐标体系,尽管左上角是原点,但横向向上滑动时distanceY为正 if(currentBrightness 0){ currentBrightness-=8; } if(currentBrightness<0){ currentBrightness=0; } } mProgressIndicator.setBackgroundResource(R.drawable.liangdu); progressBar.setProgress(currentBrightness); changeAppBrightness(mContext,currentBrightness); } } //设置当前音量 privatevoidsetCurrentVolume(floatdistanceX,floatdistanceY,floatslop){ currentVolume=audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC);//获取当前值 if(Math.abs(distanceY)>Math.abs(distanceX)){//纵向移动大于横向移动 if(distanceY>=slop){//上滑音量调大,注意横屏时的坐标体系,尽管左上角是原点,但横向向上滑动时distanceY为正 if(currentVolume 0){ currentVolume--; if(currentVolume==0){//静音,设定静音独有的图片 mProgressIndicator.setBackgroundResource(R.drawable.jingying); } } } progressBar.setProgress(currentVolume); audiomanager.setStreamVolume(AudioManager.STREAM_MUSIC,currentVolume,0); } } //设置视频亮度 privatevoidsetVideoBrightness(){ progressBar.setMax(maxBrightness); progressBar.setProgress(currentBrightness); mProgressIndicator.setBackgroundResource(R.drawable.liangdu); GESTURE_FLAG=GESTURE_MODIFY_BRIGHTNESS; } //设置视频音量 privatevoidsetVideoVolume(){ progressBar.setMax(maxVolume); progressBar.setProgress(currentVolume); mProgressIndicator.setBackgroundResource(R.drawable.yinliang); GESTURE_FLAG=GESTURE_MODIFY_VOLUME; } //改变系统亮度 publicvoidchangeAppBrightness(Contextcontext,intbrightness){ Windowwindow=((Activity)context).getWindow(); WindowManager.LayoutParamslp=window.getAttributes(); if(brightness==-1){ lp.screenBrightness=WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; }else{ lp.screenBrightness=(brightness<=0?1:brightness)/255f; } window.setAttributes(lp); } publicStringgetTimeString(intsecond){ inttemp=second/1000; inthh=temp/3600; SimpleDateFormatsdf; if(0!=hh){ sdf=newSimpleDateFormat("HH:mm:ss"); }else{ sdf=newSimpleDateFormat("mm:ss"); } Stringformat=sdf.format(newDate(second)); returnformat; } //进度条改变 @Override publicvoidonProgressChanged(SeekBarseekBar,intprogress,booleanfromUser){ StringtimeString=getTimeString(progress); id_video_time.setText(timeString); } //开始拖动 @Override publicvoidonStartTrackingTouch(SeekBarseekBar){ showLong(); videoBusiness.removeUIMessage(); } //结束拖动 @Override publicvoidonStopTrackingTouch(SeekBarseekBar){ showController(); intprogress=seekBar.getProgress(); videoBusiness.seekToPlay(progress); } }
4.下载地址
VideoView原生自定义视频播放器
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。