默认打开播放器播放视频时,视频页面的上部与下部的控制栏都是隐藏的,单击视频后显示,再单击隐藏,长按视频后暂停,再长按就播放。同时解决了一个消失与隐藏的一个小bug
代码已托管在码云上,可以下载来看,地址:
https://git.oschina.net/joy_yuan/MobilePlayer
一、实现显示与隐藏控制栏
要在手机上识别单击、双击,长按等手势,安卓有个专门的类来处理,即GestureDetector---手势识别器。要使用手势识别器,就有如下3步
1、声明识别器,实例化识别器
2、重写识别器里的单击、双击,长按方法
3、将点击屏幕产生的回调事件,作为参数传递给识别器的onTouchEvent(event),然后在第2步中处理特定的点击事件回调方法
在显示控制栏后,如果三秒没有操作,则自动隐藏控制栏,利用handler的延迟发送消息机制来实现。
具体代码如下:
private GestureDetector dector; // 手势识别器 dector=new GestureDetector(this,new GestureDetector.SimpleOnGestureListener(){ /** * 长按触发的回调函数 * @param e */ @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); startAndPause(); Toast.makeText(SystemVideoPlayer.this,"长按里屏幕",Toast.LENGTH_SHORT).show(); } /** * 双击触发的函数 * @param e * @return */ @Override public boolean onDoubleTap(MotionEvent e) { //Toast.makeText(SystemVideoPlayer.this,"双击了屏幕",Toast.LENGTH_SHORT).show(); isMediaControllerShow(); return super.onDoubleTap(e); } /** * 单击触发的函数 * @param e * @return */ @Override public boolean onSingleTapConfirmed(MotionEvent e) { //Toast.makeText(SystemVideoPlayer.this,"单击了屏幕",Toast.LENGTH_SHORT).show(); handler.removeMessages(HIDEVIDEO); isMediaControllerShow(); if (isShow){ handler.sendEmptyMessageDelayed(HIDEVIDEO,3000); } return super.onSingleTapConfirmed(e); } }); //利用onTouchEvent,传递event事件给手势识别器,否则无法触发手势识别器的回调方法 @Override public boolean onTouchEvent(MotionEvent event) { dector.onTouchEvent(event); return super.onTouchEvent(event); }
在这里通过单击、双击、长按的方式,来使控制器栏的visiable是显示还是隐藏。
二、解决产生的bug
当我们单击视频后,显示了控制栏,然后拖动seekbar进度条不放,三秒后,控制栏会消失,这是我们拖动控制栏还是可以控制视频的播放进度。这样的用户体验很差。
解决方案是,在seekbar的变化监听中,当用户点击了seekbar后,就通过handler的removeMessages(HIDDENVIDEO)来移除发送的隐藏控制栏的消息。而在用户离开seekbar后的回调方法中,重新发送延迟三秒的隐藏可控制栏的消息,具体代码如下:
/** * 视频播放框中的进度条拖拽变化的监听 */ class VideoOnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener { /** * 手指在seekbar上滑动时触发 * @param seekBar * @param progress * @param fromUser 是否是人为的滑动导致的seekbar变化,系统自动滑动也会导致这个回调方法 */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser){ videoview.seekTo(progress); //可以查看mediaplayer的声明周期图,里面有这个方法。 } } /** * 点击seekbar时触发 * @param seekBar */ @Override public void onStartTrackingTouch(SeekBar seekBar) { //当手在点击seekbar时,阻止handler发消息去隐藏控制栏 handler.removeMessages(HIDEVIDEO); } /** * 离开seekbar时触发 * @param seekBar */ @Override public void onStopTrackingTouch(SeekBar seekBar) { //当手离开seekbar时,触发handler发消息去隐藏控制栏 handler.sendEmptyMessageDelayed(HIDEVIDEO,3000); } }
同样,在控制栏显示时,不管是点击停止、播放按钮,还是点击下一个、上一个等按钮,都要实现上面的逻辑,即先移除消息,再重新发送延迟的消息
@Override public void onClick(View v) { if ( v == btnVoice ) { // Handle clicks for btnVoice } else if ( v == switchPlayer ) { // Handle clicks for switchPlayer } else if ( v == btExit ) { // Handle clicks for btExit 退出 finish(); } else if ( v == btVideoPre ) { // Handle clicks for btVideoPre 播放上一个视频 if (medialist!=null&&medialist.size()>0){ position-=1; if (position<=0){ position=medialist.size()-1; } MediaItem mediaitem=medialist.get(position); tvName.setText(mediaitem.getName()); videoview.setVideoPath(mediaitem.getData()); }else if (uri!=null){ tvName.setText(uri.toString()); videoview.setVideoURI(uri); } } else if ( v == btVideoStartPause ) { // Handle clicks for btVideoStartPause 播放暂停与启动 startAndPause(); } else if ( v == btNext ) { // Handle clicks for btNext 播放下一个 if (medialist!=null&&medialist.size()>0){ position+=1; if (position>=medialist.size()){ position=0; } MediaItem mediaItem = medialist.get(position); tvName.setText(mediaItem.getName()); videoview.setVideoPath(mediaItem.getData()); }else if (uri!=null){ //把上一个下一个按钮设置灰色 tvName.setText(uri.toString()); videoview.setVideoURI(uri); btNext.setEnabled(false); btNext.setBackgroundResource(R.drawable.btn_next_gray); } } else if ( v == btVideoSwitchScreen ) { // Handle clicks for btVideoSwitchScreen } handler.removeMessages(HIDEVIDEO); handler.sendEmptyMessageDelayed(HIDEVIDEO,3000); }