手機影音第八天 控制視頻播放頁面的上面與下邊的控制器布局的消失與隱藏
默認打開播放器播放視頻時,視頻頁面的上部與下部的控制欄都是隱藏的,單擊視頻後顯示,再單擊隱藏,長按視頻後暫停,再長按就播放。同時解決了一個消失與隱藏的一個小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); }
本文出自 “YuanGuShi” 博客,請務必保留此出處http://cm0425.blog.51cto.com/10819451/1949131
手機影音第八天 控制視頻播放頁面的上面與下邊的控制器布局的消失與隱藏