Android videoview 橫豎屏切換,主要是對各種狀态封裝了一下,以後移植不需要考慮這些狀态。然後橫豎屏,對布局結構有點限制,要處于上層才能全屏
public class MainActivity extends Activity {
public static final String URL_VIDEO = "http://static.wezeit.com/o_1a9jjk9021fkt7vs1mlo16i91gvn9.mp4";
@Bind(R.id.webview)
public WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initWidget();
setupListener();
loadData();
}
private void initView(){
ButterKnife.bind(this);
initFakeStatusBarHeight(true);
}
private void initWidget(){
initWebViewSetting(mWebView);
}
private void setupListener(){
setupWebViewListener();
}
private void loadData(){
View view = findViewById(R.id.activity_video_rl);
initVideoMode(view);
String url = "http://www.wezeit.com/wap/297121.html";
loadWebviewUrl(url);
}
protected void loadWebviewUrl(String url){
DebugTools.d("js2 discovery2 jump3 vote2 news2 current url: " + url);
if(!TextUtils.isEmpty(url)){
mWebView.loadUrl(url);
}
}
protected int mPixelInsetTop;
protected void initFakeStatusBarHeight(boolean isNewsPage){
View statusbarBgLayout = (View)findViewById(R.id.statusbar_bg_layout);
if(statusbarBgLayout == null){
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mPixelInsetTop = CommonTools.getStatusbarHeight(this);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)statusbarBgLayout.getLayoutParams();
params.height = mPixelInsetTop;
statusbarBgLayout.setLayoutParams(params);
statusbarBgLayout.setBackgroundResource(R.color.black);
}else{
mPixelInsetTop = ;
statusbarBgLayout.setVisibility(View.GONE);
}
}
//----------videoview----------------
private VideoViewHolder mVideoHolder;
private VideoView mVideoView;
private VideoViewHolderControl mVideoControl;
private void initVideoMode(View view){
showFullScreen(false);
mVideoView = (VideoView) view.findViewById(R.id.videoview);
mVideoHolder = new VideoViewHolder(view);
mVideoHolder.imgIv.setImageResource(R.mipmap.index);
mVideoControl = new VideoViewHolderControl(mVideoHolder, mVideoView, URL_VIDEO);
setupVideoControlListener(mVideoControl);
mVideoControl.setup();
setVideoViewLayout(false);
}
private void setupVideoControlListener(VideoViewHolderControl control){
control.setOnVideoControlListener(new VideoViewHolderControl.OnVideoControlProxy() {
@Override
public void onCompletion() {
DebugTools.d("video2 onCompletion");
setFullScreen(false);
}
@Override
public void onClickHalfFullScreen() {
boolean isFull = isFullScreen();
setFullScreen(!isFull);
}
@Override
public void onError(int code, String msg) {
}
});
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
initHalfFullState(true);
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
initHalfFullState(false);
}
}
private void initHalfFullState(boolean isFull){
DebugTools.d("video2 initHalfFullState isFull: " + isFull);
setVideoViewLayout(isFull);
showFullScreen(isFull);
}
//---------videoview fullscreen---------
private void showFullScreen(boolean isFullScreen){
if(isFullScreen){
// //不顯示程式的标題欄
hideNavigationBar();
}else{
showNavigationBar();
}
}
protected void setFullScreen(boolean isFull){
if(isFull){
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}else{
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
protected boolean isFullScreen(){
return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}
private void showNavigationBar(){
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
public void hideNavigationBar() {
int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN; // hide status bar
getWindow().getDecorView().setSystemUiVisibility(uiFlags);
}
private void setVideoViewLayout(boolean isFull){
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)mVideoHolder.videoRl.getLayoutParams();
RelativeLayout.LayoutParams controlParams = (RelativeLayout.LayoutParams)mVideoHolder.mediaControl.getLayoutParams();
RelativeLayout.LayoutParams indexImageParams = (RelativeLayout.LayoutParams)mVideoHolder.imgIv.getLayoutParams();
int videoMarginTop = (int)getResources().getDimension(R.dimen.library_video_video_margin_top) + mPixelInsetTop;
if(isFull){
params.height = LayoutParams.MATCH_PARENT;
params.addRule(RelativeLayout.CENTER_IN_PARENT);
params.setMargins(, , , );
controlParams.setMargins(, , , );
indexImageParams.height = LayoutParams.MATCH_PARENT;
indexImageParams.setMargins(, , , );
}else{
params.height = DisplayUtil.dip2px(this, );
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.setMargins(, videoMarginTop, , );
controlParams.setMargins(, , , );
indexImageParams.height = DisplayUtil.dip2px(this, );
indexImageParams.setMargins(, , , );
}
mVideoHolder.videoRl.setLayoutParams(params);
mVideoHolder.mediaControl.setLayoutParams(controlParams);
mVideoHolder.imgIv.setLayoutParams(indexImageParams);
}
//--------------webview--------------
protected void initWebViewStorage(WebView webview){
webview.getSettings().setDomStorageEnabled(true);
webview.getSettings().setAppCacheMaxSize(**);
String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
webview.getSettings().setAllowFileAccess(true);
webview.getSettings().setAppCacheEnabled(true);
webview.getSettings().setDatabaseEnabled(true);
webview.getSettings().setDatabasePath(appCachePath);
}
protected void initWebViewSetting(WebView webview){
WebSettings webseting = webview.getSettings();
// webseting.setRenderPriority(RenderPriority.HIGH);
webseting.setJavaScriptEnabled(true);
// webseting.setPluginsEnabled(true);
webseting.setSupportZoom(true);
webview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webseting.setUseWideViewPort(true);
webseting.setLoadWithOverviewMode(true);
initWebViewStorage(webview);
}
protected void setupWebViewListener(){
mWebView.setWebViewClient(new WebViewClient() {
});
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){
handleClickBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void handleClickBack(){
if(isFullScreen()){
setFullScreen(false);
return;
}
if (mWebView != null){
mWebView.onPause();
}
finish();
}
@Override
protected void onDestroy() {
ButterKnife.unbind(this);
super.onDestroy();
}
}
VideoViewHolderControl,狀态控制器,裡面內建了視訊的基本操作
public class VideoViewHolderControl {
private VideoViewHolder mHolder;
private VideoView mVideoView;
private String mUrl;
private boolean mIsFullScreen = false;
private boolean mIsFullScreenMode = false;
public VideoViewHolderControl(VideoViewHolder holder, VideoView videoView, String url){
mHolder = holder;
mVideoView = videoView;
mUrl = url;
// mUrl = "http://img.owspace.com/V_tnh2100_1453346133.2098116.m3u8";
}
public void setup(){
setupPlayListener(mHolder);
showInitStateState(mHolder);
}
public void play(){
if(mHolder != null){
handleStartPlayVideo(mHolder);
}
}
public void setIsFullScreenMode(boolean isFullMode){
mIsFullScreenMode = isFullMode;
if(mIsFullScreenMode){
if(mHolder != null){
mHolder.halfFullIb.setImageResource(R.mipmap.library_video_mediacontroller_to_half);
hideFullHalIb(mHolder);
}
}
}
private void hideFullHalIb(VideoViewHolder holder){
if(holder == null){
return;
}
holder.halfFullIb.setVisibility(View.GONE);
RelativeLayout.LayoutParams totalTimeParams = (RelativeLayout.LayoutParams)holder.totalTimeTv.getLayoutParams();
totalTimeParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
totalTimeParams.setMargins(, , (int)DisplayUtil.dpToPx(), );
holder.totalTimeTv.setLayoutParams(totalTimeParams);
}
private void setupPlayListener(final VideoViewHolder holder){
holder.playPauseIb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handleStartPlayVideo(holder);
}
});
holder.imgIv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handleStartPlayVideo(holder);
}
});
holder.playSymbolIv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handleStartPlayVideo(holder);
}
});
if(holder.halfFullIb != null){
holder.halfFullIb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(mIsFullScreenMode){
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickHalfFullScreen();
}
}else{
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickHalfFullScreen();
mIsFullScreen = !mIsFullScreen;
setHalfFullScreenState(holder, mIsFullScreen);
}
}
}
});
}
if(holder.backIb != null){
holder.backIb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(mIsFullScreenMode){
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickHalfFullScreen();
}
}
}
});
}
}
private void setHalfFullScreenState(VideoViewHolder holder, boolean isFull){
if(isFull){
holder.halfFullIb.setImageResource(R.mipmap.library_video_mediacontroller_to_half);
}else{
holder.halfFullIb.setImageResource(R.mipmap.library_video_mediacontroller_to_full);
}
}
private void handleStartPlayVideo(VideoViewHolder holder){
DebugTools.d("video2 handleStartPlayVideo mPlayState: " + mPlayState);
if(mPlayState == PlayState.INIT){
if(mVideoView == null){
return;
}
if(TextUtils.isEmpty(mUrl)){
if(mOnVideoControlListener != null){
mOnVideoControlListener.onError(, "視訊位址為空");
}
return;
}
if(mVideoView.getVisibility() != View.VISIBLE){
mVideoView.setVisibility(View.VISIBLE);
}
initVideoView(holder, mVideoView);
handlePrepareVideo(holder);
setupVideoViewListener(mVideoView, holder);
DebugTools.d("video2 handleStartPlayVideo setVideoPath-------------");
mVideoView.setVideoPath(mUrl);
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickPlay();
}
}else if(mPlayState == PlayState.PAUSE){
handlePlayVideo(holder);
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickResume();
}
}else if(mPlayState == PlayState.PLAYING){
handlePauseVideo(holder);
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickPause();
}
}
}
private void handlePrepareVideo(final VideoViewHolder holder){
showPreparePlayState(holder);
}
private void handlePlayVideo(final VideoViewHolder holder){
showPlayingState(holder);;
mVideoView.start();
}
private void handlePauseVideo(final VideoViewHolder holder){
showPauseState(holder);
mVideoView.pause();
}
public void pause(){
if(mPlayState == PlayState.PLAYING){
handlePauseVideo(mHolder);
if(mOnVideoControlListener != null){
mOnVideoControlListener.onClickPause();
}
}else if(mPlayState == PlayState.PREPARE){
stop();
}
}
public void stop(){
if(!isInIdleState()){
stopVideo(mHolder, mVideoView);
}
}
private void stopVideo(VideoViewHolder holder, VideoView videoView){
DebugTools.d("video2 stopVideo videoView null: " + (videoView == null));
if(videoView != null){
videoView.setVisibility(View.GONE);
videoView.stopPlayback();
holder.pb.setVisibility(View.GONE);
showInitStateState(holder);
}
}
private boolean isInIdleState(){
return mPlayState == PlayState.INIT;
}
private PlayState mPlayState = PlayState.INIT;
private enum PlayState{
INIT, PREPARE, PLAYING, PAUSE
}
private void showPlayingState(VideoViewHolder holder){
mPlayState = PlayState.PLAYING;
updateViewVisibleState(holder.pb, View.GONE);
updateViewVisibleState(holder.imgIv, View.INVISIBLE);
updateViewVisibleState(holder.seekBar, View.VISIBLE);
updateViewVisibleState(holder.playSymbolIv, View.INVISIBLE);
holder.playPauseIb.setImageResource(R.mipmap.library_video_mediacontroller_pause);
sendDismissVideoControlBarDelay(holder);
}
private void showPauseState(VideoViewHolder holder){
mPlayState = PlayState.PAUSE;
updateViewVisibleState(holder.pb, View.GONE);
updateViewVisibleState(holder.imgIv, View.INVISIBLE);
updateViewVisibleState(holder.seekBar, View.VISIBLE);
updateViewVisibleState(holder.mediaControl, View.VISIBLE);
updateViewVisibleState(holder.backIb, View.VISIBLE);
updateViewVisibleState(holder.playSymbolIv, View.VISIBLE);
holder.playPauseIb.setImageResource(R.mipmap.library_video_mediacontroller_play);
mHandler.removeMessages(Constants.MSG_DISMISS_VIDEO_CONTROL_BAR);
}
private void showPreparePlayState(VideoViewHolder holder){
mPlayState = PlayState.PREPARE;
if(!mIsFullScreenMode){
updateViewVisibleState(holder.imgIv, View.INVISIBLE);
}
holder.playPauseIb.setImageResource(R.mipmap.library_video_mediacontroller_pause);
updateViewVisibleState(holder.pb, View.VISIBLE);
updateViewVisibleState(holder.seekBar, View.VISIBLE);
updateViewVisibleState(holder.mediaControl, View.INVISIBLE);
updateViewVisibleState(holder.backIb, View.INVISIBLE);
updateViewVisibleState(holder.playSymbolIv, View.INVISIBLE);
}
private void showInitStateState(VideoViewHolder holder){
mPlayState = PlayState.INIT;
holder.seekBar.setProgress();
holder.playPauseIb.setImageResource(R.mipmap.library_video_mediacontroller_play);
updateViewVisibleState(holder.pb, View.GONE);
updateViewVisibleState(holder.imgIv, View.VISIBLE);
updateViewVisibleState(holder.seekBar, View.INVISIBLE);
updateViewVisibleState(holder.mediaControl, View.INVISIBLE);
updateViewVisibleState(holder.backIb, View.INVISIBLE);
updateViewVisibleState(holder.playSymbolIv, View.VISIBLE);
mHandler.removeMessages(Constants.MSG_DISMISS_VIDEO_CONTROL_BAR);
}
private void updateViewVisibleState(View view, int visibleState){
if(!mIsFullScreenMode && view == mHolder.backIb){
return;
}
if(view == null){
return;
}
if(view.getVisibility() != visibleState){
view.setVisibility(visibleState);
}
}
private void initVideoView(VideoViewHolder holder, VideoView videoView){
videoView.setMediaController(holder.mediaControl);
holder.mediaControl.setMediaPlayer(videoView);
//讓VideiView擷取焦點
videoView.requestFocus();
}
private void setupVideoViewListener(final VideoView videoView, final VideoViewHolder holder){
videoView.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
DebugTools.d("video2 setOnPreparedListener onCompletion---, mPlayState: " + mPlayState);
if(videoView != null){
if(mp != null){
mp.reset();
}
videoView.seekTo();
videoView.stopPlayback();
showInitStateState(holder);
}
if(mOnVideoControlListener != null){
mOnVideoControlListener.onCompletion();
}
}
});
videoView.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// mVideoView.setBackgroundColor(Color.TRANSPARENT);
DebugTools.d("video2 setOnPreparedListener onPrepared, mPlayState: " + mPlayState);
// if(!(mPlayState == PlayState.PREPARE || mPlayState == PlayState.INIT)){
// return;
// }
mVideoView.start();
showPlayingState(holder);
holder.mediaControl.show();
updateViewVisibleState(holder.backIb, View.VISIBLE);
mHandler.sendEmptyMessageDelayed(Constants.MSG_SET_VIDEO_VIEW_TRANSPARENT,
Constants.DELAY_MSG_SET_VIDEO_VIEW_TRANSPARENT);
sendDismissVideoControlBarDelay(holder);
DebugTools.d("video2 onPrepared mProgress: " + mProgress);
if(mIsFullScreenMode && mProgress > ){
seekTo(mProgress);
}
if(mOnVideoControlListener != null){
mOnVideoControlListener.onPrepared();
}
}
});
((WylVideoView)videoView).setOnGestureListener(new OnGestureListener() {
@Override
public void onSingleTapConfirmed() {
boolean isShow = (holder.mediaControl.getVisibility() == View.VISIBLE);
showVideoControlBar(holder, !isShow);
}
@Override
public void onDoubleTap() {
handleStartPlayVideo(holder);
}
});
if(holder.videoRl != null){
holder.videoRl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
boolean isShow = (holder.mediaControl.getVisibility() == View.VISIBLE);
showVideoControlBar(holder, !isShow);
}
});
}
holder.mediaControl.setAdditionalSeekBarListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
DebugTools.d("video2 sbar2 onStopTrackingTouch");
sendDismissVideoControlBarDelay(holder);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
DebugTools.d("video2 sbar2 onStartTrackingTouch");
mHandler.removeMessages(Constants.MSG_DISMISS_VIDEO_CONTROL_BAR);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
DebugTools.d("video2 sbar2 onProgressChanged");
}
});
DebugTools.d("video2 setupVideoViewListener when click play video");
}
private void showVideoControlBar(final VideoViewHolder holder, final boolean isShow){
mHandler.removeMessages(Constants.MSG_DISMISS_VIDEO_CONTROL_BAR);
updateViewVisibleState(holder.mediaControl, View.VISIBLE);
updateViewVisibleState(holder.backIb, View.VISIBLE);
Animation anim = null;
if(isShow){
anim = new TranslateAnimation(, , , );
}else{
anim = new TranslateAnimation(, , , );
}
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if(isShow){
updateViewVisibleState(holder.mediaControl, View.VISIBLE);
updateViewVisibleState(holder.backIb, View.VISIBLE);
sendDismissVideoControlBarDelay(holder);
}else{
updateViewVisibleState(holder.mediaControl, View.INVISIBLE);
updateViewVisibleState(holder.backIb, View.INVISIBLE);
}
}
});
anim.setDuration();
holder.mediaControl.startAnimation(anim);
if(holder.backIb != null){
Animation backAnim = null;
if(isShow){
backAnim = new AlphaAnimation(, );
}else{
backAnim = new AlphaAnimation(, );
}
backAnim.setDuration();
holder.backIb.startAnimation(backAnim);
}
}
private void sendDismissVideoControlBarDelay(VideoViewHolder holder){
Message msg = mHandler.obtainMessage(Constants.MSG_DISMISS_VIDEO_CONTROL_BAR, holder);
mHandler.sendMessageDelayed(msg, Constants.DELAY_MSG_DISMISS_VIDEO_CONTROL_BAR);
}
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch(msg.what){
case Constants.MSG_SET_VIDEO_VIEW_TRANSPARENT:
setVideoViewTranslate();
break;
case Constants.MSG_DISMISS_VIDEO_CONTROL_BAR:
VideoViewHolder holder = (VideoViewHolder)msg.obj;
showVideoControlBar(holder, false);
break;
}
};
};
private void setVideoViewTranslate(){
if(mVideoView != null){
mVideoView.setBackgroundColor(Color.TRANSPARENT);
}
}
private int mProgress;
public void setProgress(int pos){
mProgress = pos;
}
private void seekTo(int pos){
if(mHolder != null && mHolder.mediaControl != null){
mHolder.mediaControl.seekTo(pos);
}
}
public static class VideoViewHolder{
public WylMediaControl mediaControl;
// public ImageView shareIv;
public ImageView playPauseIb;
public SeekBar seekBar;
public ProgressBar pb;
public ImageView imgIv;
public ImageView playSymbolIv;
public RelativeLayout videoRl;
public ImageButton halfFullIb;
public ImageButton backIb;
public TextView totalTimeTv;
public VideoViewHolder(View convertView){
mediaControl = (WylMediaControl) convertView.findViewById(R.id.media_control);
// shareIv = (ImageView) convertView.findViewById(R.id.mediacontroller_share_iv);
playPauseIb = (ImageView) convertView.findViewById(R.id.mediacontroller_play_pause);
seekBar = (SeekBar) convertView.findViewById(R.id.mediacontroller_seekbar);
pb = (ProgressBar) convertView.findViewById(R.id.loading_pb);
imgIv = (ImageView) convertView.findViewById(R.id.video_image_iv);
playSymbolIv = (ImageView) convertView.findViewById(R.id.play_symbol_iv);
videoRl = (RelativeLayout) convertView.findViewById(R.id.video_rl);
halfFullIb = (ImageButton) convertView.findViewById(R.id.mediacontroller_half_full_ib);
// backIb = (ImageButton) convertView.findViewById(R.id.video_back_iv);
totalTimeTv = (TextView) convertView.findViewById(R.id.mediacontroller_time_total);
}
}
private OnVideoControlListener mOnVideoControlListener;
public void setOnVideoControlListener(OnVideoControlListener listener){
mOnVideoControlListener = listener;
}
public interface OnVideoControlListener{
public void onClickPlay();
public void onPrepared();
public void onClickResume();
public void onClickPause();
public void onCompletion();
public void onClickHalfFullScreen();
public void onError(int code, String msg);
}
public static class OnVideoControlProxy implements OnVideoControlListener{
@Override
public void onClickPlay() {
}
@Override
public void onPrepared() {
}
@Override
public void onClickResume() {
}
@Override
public void onClickPause() {
}
@Override
public void onCompletion() {
}
@Override
public void onClickHalfFullScreen() {
}
@Override
public void onError(int code, String msg) {
}
}
}
WylMediaControl,重寫了下系統的MediaController,友善自定義
public class WylMediaControl extends MediaController {
private MediaPlayerControl mPlayer;
private Context mContext;
private View mAnchor;
private View mRoot;
private WindowManager mWindowManager;
private Window mWindow;
private View mDecor;
private WindowManager.LayoutParams mDecorLayoutParams;
private ProgressBar mProgress;
private TextView mEndTime, mCurrentTime;
private boolean mShowing;
private boolean mDragging;
private static final int sDefaultTimeout = ;
private static final int FADE_OUT = ;
private static final int SHOW_PROGRESS = ;
private boolean mUseFastForward;
private boolean mFromXml;
private boolean mListenersSet;
private OnClickListener mNextListener, mPrevListener;
StringBuilder mFormatBuilder;
Formatter mFormatter;
private ImageView mPauseButton;
// private ImageButton mPauseButton;
private ImageButton mFfwdButton;
private ImageButton mRewButton;
private ImageButton mNextButton;
private ImageButton mPrevButton;
private ImageView mShareBtn;
public WylMediaControl(Context context, AttributeSet attrs) {
super(context, attrs);
mRoot = this;
mContext = context;
mUseFastForward = true;
mFromXml = true;
}
@Override
public void onFinishInflate() {
if (mRoot != null)
initControllerView(mRoot);
}
public WylMediaControl(Context context, boolean useFastForward) {
super(context);
mContext = context;
mUseFastForward = useFastForward;
initFloatingWindowLayout();
// initFloatingWindow();
}
public WylMediaControl(Context context) {
this(context, true);
}
// private void initFloatingWindow() {
// mWindowManager =
// (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
// mWindow = PolicyManager.makeNewWindow(mContext);
// mWindow.setWindowManager(mWindowManager, null, null);
// mWindow.requestFeature(Window.FEATURE_NO_TITLE);
// mDecor = mWindow.getDecorView();
// mDecor.setOnTouchListener(mTouchListener);
// mWindow.setContentView(this);
// mWindow.setBackgroundDrawableResource(android.R.color.transparent);
//
// // While the media controller is up, the volume control keys should
// // affect the media stream type
// mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);
//
// setFocusable(true);
// setFocusableInTouchMode(true);
// setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
// requestFocus();
// }
// Allocate and initialize the static parts of mDecorLayoutParams. Must
// also call updateFloatingWindowLayout() to fill in the dynamic parts
// (y and width) before mDecorLayoutParams can be used.
private void initFloatingWindowLayout() {
mDecorLayoutParams = new WindowManager.LayoutParams();
WindowManager.LayoutParams p = mDecorLayoutParams;
p.gravity = Gravity.TOP | Gravity.LEFT;
p.height = LayoutParams.WRAP_CONTENT;
p.x = ;
p.format = PixelFormat.TRANSLUCENT;
p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
p.token = null;
p.windowAnimations = ; // android.R.style.DropDownAnimationDown;
}
// Update the dynamic parts of mDecorLayoutParams
// Must be called with mAnchor != NULL.
private void updateFloatingWindowLayout() {
int[] anchorPos = new int[];
mAnchor.getLocationOnScreen(anchorPos);
// we need to know the size of the controller so we can properly
// position it
// within its space
mDecor.measure(MeasureSpec.makeMeasureSpec(mAnchor.getWidth(),
MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(
mAnchor.getHeight(), MeasureSpec.AT_MOST));
WindowManager.LayoutParams p = mDecorLayoutParams;
p.width = mAnchor.getWidth();
p.x = anchorPos[] + (mAnchor.getWidth() - p.width) / ;
p.y = anchorPos[] + mAnchor.getHeight() - mDecor.getMeasuredHeight();
}
// This is called whenever mAnchor's layout bound changes
private OnLayoutChangeListener mLayoutChangeListener = new OnLayoutChangeListener() {
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
updateFloatingWindowLayout();
if (mShowing) {
mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);
}
}
};
private OnTouchListener mTouchListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mShowing) {
hide();
}
}
return false;
}
};
@Override
public void setMediaPlayer(MediaPlayerControl player) {
mPlayer = player;
updatePausePlay();
}
/**
* Set the view that acts as the anchor for the control view. This can for
* example be a VideoView, or your Activity's main view. When VideoView
* calls this method, it will use the VideoView's parent as the anchor.
*
* @param view
* The view to which to anchor the controller when it is visible.
*/
public void setAnchorView(View view) {
// if (mAnchor != null) {
// mAnchor.removeOnLayoutChangeListener(mLayoutChangeListener);
// }
mAnchor = view;
// if (mAnchor != null) {
// mAnchor.addOnLayoutChangeListener(mLayoutChangeListener);
// }
if (!mFromXml) {
// FrameLayout.LayoutParams frameParams = new
// FrameLayout.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT
// );
//
// removeAllViews();
// View v = makeControllerView();
// addView(v, frameParams);
}
}
private MediaControlListener mMediaControlListener;
public interface MediaControlListener{
public void onClickStart();
public void onClickPause();
}
/**
* Create the view that holds the widgets that control playback. Derived
* classes can override this to create their own.
*
* @return The controller view.
* @hide This doesn't work as advertised
*/
// protected View makeControllerView() {
// LayoutInflater inflate = (LayoutInflater)
// mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// mRoot = inflate.inflate(com.android.internal.R.layout.media_controller,
// null);
//
// initControllerView(mRoot);
//
// return mRoot;
// }
private void initControllerView(View v) {
mPauseButton = (ImageView) v.findViewById(R.id.mediacontroller_play_pause);
// if (mPauseButton != null) {
// mPauseButton.requestFocus();
// mPauseButton.setOnClickListener(mPauseListener);
// }
if (mShareBtn != null) {
// mShareBtn.setOnClickListener(mShareListener);
}
// mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
// if (mFfwdButton != null) {
// mFfwdButton.setOnClickListener(mFfwdListener);
// if (!mFromXml) {
// mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE
// : View.GONE);
// }
// }
//
// mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
// if (mRewButton != null) {
// mRewButton.setOnClickListener(mRewListener);
// if (!mFromXml) {
// mRewButton.setVisibility(mUseFastForward ? View.VISIBLE
// : View.GONE);
// }
// }
// By default these are hidden. They will be enabled when
// setPrevNextListeners() is called
// mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
// if (mNextButton != null && !mFromXml && !mListenersSet) {
// mNextButton.setVisibility(View.GONE);
// }
// mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
// if (mPrevButton != null && !mFromXml && !mListenersSet) {
// mPrevButton.setVisibility(View.GONE);
// }
mProgress = (ProgressBar) v.findViewById(R.id.mediacontroller_seekbar);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
seeker.setOnSeekBarChangeListener(mSeekListener);
}
mProgress.setMax();
}
mEndTime = (TextView) v.findViewById(R.id.mediacontroller_time_total);
mCurrentTime = (TextView) v.findViewById(R.id.mediacontroller_time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
installPrevNextListeners();
}
/**
* Show the controller on screen. It will go away automatically after 3
* seconds of inactivity.
*/
public void show() {
show(sDefaultTimeout);
}
/**
* Disable pause or seek buttons if the stream cannot be paused or seeked.
* This requires the control interface to be a MediaPlayerControlExt
*/
private void disableUnsupportedButtons() {
try {
if (mPauseButton != null && !mPlayer.canPause()) {
mPauseButton.setEnabled(false);
}
if (mRewButton != null && !mPlayer.canSeekBackward()) {
mRewButton.setEnabled(false);
}
if (mFfwdButton != null && !mPlayer.canSeekForward()) {
mFfwdButton.setEnabled(false);
}
} catch (IncompatibleClassChangeError ex) {
// We were given an old version of the interface, that doesn't have
// the canPause/canSeekXYZ methods. This is OK, it just means we
// assume the media can be paused and seeked, and so we don't
// disable
// the buttons.
}
}
/**
* Show the controller on screen. It will go away automatically after
* 'timeout' milliseconds of inactivity.
*
* @param timeout
* The timeout in milliseconds. Use 0 to show the controller
* until hide() is called.
*/
public void show(int timeout) {
if (!mShowing && mAnchor != null) {
if (mFromXml) {
setVisibility(View.VISIBLE);
// return;
}
setProgress();
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
disableUnsupportedButtons();
// updateFloatingWindowLayout();
// mWindowManager.addView(mDecor, mDecorLayoutParams);
mShowing = true;
}
updatePausePlay();
// cause the progress bar to be updated even if mShowing
// was already true. This happens, for example, if we're
// paused with the progress bar showing the user hits play.
mHandler.sendEmptyMessage(SHOW_PROGRESS);
DebugTools.d("control2 show");
Message msg = mHandler.obtainMessage(FADE_OUT);
if (timeout != ) {
mHandler.removeMessages(FADE_OUT);
mHandler.sendMessageDelayed(msg, timeout);
}
}
public boolean isShowing() {
return mShowing;
}
/**
* Remove the controller from the screen.
*/
public void hide() {
// if (mAnchor == null)
// return;
//
// if (mShowing) {
// try {
// mHandler.removeMessages(SHOW_PROGRESS);
// mWindowManager.removeView(mDecor);
// } catch (IllegalArgumentException ex) {
// Log.w("MediaController", "already removed");
// }
// mShowing = false;
// }
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int pos;
switch (msg.what) {
case FADE_OUT:
// hide();
break;
case SHOW_PROGRESS:
pos = setProgress();
if (!mDragging && mShowing && mPlayer.isPlaying()) {
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, - (pos % ));
}
break;
}
}
};
private String stringForTime(int timeMs) {
int totalSeconds = timeMs / ;
int seconds = totalSeconds % ;
int minutes = (totalSeconds / ) % ;
int hours = totalSeconds / ;
mFormatBuilder.setLength();
if (hours > ) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds)
.toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}
private int setProgress() {
DebugTools.d("control2 setProgress");
if (mPlayer == null || mDragging) {
return ;
}
int position = mPlayer.getCurrentPosition();
int duration = mPlayer.getDuration();
DebugTools.d("control2 setProgress position: " + position + " duration: " + duration);
if (mProgress != null) {
if (duration > ) {
// use long to avoid overflow
long pos = L * position / duration;
mProgress.setProgress((int) pos);
}
int percent = mPlayer.getBufferPercentage();
mProgress.setSecondaryProgress(percent * );
}
if (mEndTime != null)
mEndTime.setText(stringForTime(duration));
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime(position));
return position;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
show(sDefaultTimeout);
return true;
}
@Override
public boolean onTrackballEvent(MotionEvent ev) {
show(sDefaultTimeout);
return false;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
final boolean uniqueDown = event.getRepeatCount() ==
&& event.getAction() == KeyEvent.ACTION_DOWN;
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
|| keyCode == KeyEvent.KEYCODE_SPACE) {
if (uniqueDown) {
doPauseResume();
show(sDefaultTimeout);
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
if (uniqueDown && !mPlayer.isPlaying()) {
mPlayer.start();
updatePausePlay();
show(sDefaultTimeout);
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
|| keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
if (uniqueDown && mPlayer.isPlaying()) {
mPlayer.pause();
updatePausePlay();
show(sDefaultTimeout);
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_MUTE
|| keyCode == KeyEvent.KEYCODE_CAMERA) {
// don't show the controls for volume adjustment
return super.dispatchKeyEvent(event);
} else if (keyCode == KeyEvent.KEYCODE_BACK
|| keyCode == KeyEvent.KEYCODE_MENU) {
if (uniqueDown) {
hide();
}
return true;
}
show(sDefaultTimeout);
return super.dispatchKeyEvent(event);
}
private OnClickListener mPauseListener = new OnClickListener() {
public void onClick(View v) {
doPauseResume();
show(sDefaultTimeout);
}
};
private OnClickListener mShareListener = new OnClickListener() {
public void onClick(View v) {
if(mMediaControlListener != null){
// mMediaControlListener.onClickShare(v);
}
}
};
public void setMediaControlListener(MediaControlListener listener){
mMediaControlListener = listener;
}
private void updatePausePlay() {
if (mRoot == null || mPauseButton == null)
return;
// if (mPlayer.isPlaying()) {
// mPauseButton.setImageResource(R.drawable.mediacontroller_pause);
mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_pause);
// } else {
// mPauseButton.setImageResource(R.drawable.mediacontroller_play);
mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_play);
// }
}
public void doPause(){
if (mPlayer.isPlaying()) {
mPlayer.pause();
mPauseButton.setImageResource(R.mipmap.library_video_mediacontroller_play);
if(mMediaControlListener != null){
mMediaControlListener.onClickPause();
}
}
}
public void doPauseResume() {
if (mPlayer.isPlaying()) {
mPlayer.pause();
mPauseButton.setImageResource(R.mipmap.library_video_mediacontroller_play);
if(mMediaControlListener != null){
mMediaControlListener.onClickPause();
}
} else {
mPlayer.start();
mPauseButton.setImageResource(R.mipmap.library_video_mediacontroller_pause);
if(mMediaControlListener != null){
mMediaControlListener.onClickStart();
}
}
// updatePausePlay();
}
// There are two scenarios that can trigger the seekbar listener to trigger:
//
// The first is the user using the touchpad to adjust the posititon of the
// seekbar's thumb. In this case onStartTrackingTouch is called followed by
// a number of onProgressChanged notifications, concluded by
// onStopTrackingTouch.
// We're setting the field "mDragging" to true for the duration of the
// dragging
// session to avoid jumps in the position in case of ongoing playback.
//
// The second scenario involves the user operating the scroll ball, in this
// case there WON'T BE onStartTrackingTouch/onStopTrackingTouch
// notifications,
// we will simply apply the updated position without suspending regular
// updates.
private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
public void onStartTrackingTouch(SeekBar bar) {
show();
mDragging = true;
// By removing these pending progress messages we make sure
// that a) we won't update the progress while the user adjusts
// the seekbar and b) once the user is done dragging the thumb
// we will post one of these messages to the queue again and
// this ensures that there will be exactly one message queued up.
mHandler.removeMessages(SHOW_PROGRESS);
if(mAdditionalSeekListener != null){
mAdditionalSeekListener.onStartTrackingTouch(bar);
}
}
public void onProgressChanged(SeekBar bar, int progress,
boolean fromuser) {
if (!fromuser) {
// We're not interested in programmatically generated changes to
// the progress bar's position.
return;
}
long duration = mPlayer.getDuration();
long newposition = (duration * progress) / L;
mPlayer.seekTo((int) newposition);
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime((int) newposition));
if(mAdditionalSeekListener != null){
mAdditionalSeekListener.onProgressChanged(bar, progress, fromuser);
}
}
public void onStopTrackingTouch(SeekBar bar) {
mDragging = false;
setProgress();
updatePausePlay();
show(sDefaultTimeout);
// Ensure that progress is properly updated in the future,
// the call to show() does not guarantee this because it is a
// no-op if we are already showing.
mHandler.sendEmptyMessage(SHOW_PROGRESS);
if(mAdditionalSeekListener != null){
mAdditionalSeekListener.onStopTrackingTouch(bar);
}
}
};
private OnSeekBarChangeListener mAdditionalSeekListener;
public void setAdditionalSeekBarListener(OnSeekBarChangeListener listener){
mAdditionalSeekListener = listener;
}
@Override
public void setEnabled(boolean enabled) {
if (mPauseButton != null) {
mPauseButton.setEnabled(enabled);
}
if (mFfwdButton != null) {
mFfwdButton.setEnabled(enabled);
}
if (mRewButton != null) {
mRewButton.setEnabled(enabled);
}
if (mNextButton != null) {
mNextButton.setEnabled(enabled && mNextListener != null);
}
if (mPrevButton != null) {
mPrevButton.setEnabled(enabled && mPrevListener != null);
}
if (mProgress != null) {
mProgress.setEnabled(enabled);
}
disableUnsupportedButtons();
super.setEnabled(enabled);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(MediaController.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(MediaController.class.getName());
}
private OnClickListener mRewListener = new OnClickListener() {
public void onClick(View v) {
int pos = mPlayer.getCurrentPosition();
pos -= ; // milliseconds
mPlayer.seekTo(pos);
setProgress();
show(sDefaultTimeout);
}
};
private OnClickListener mFfwdListener = new OnClickListener() {
public void onClick(View v) {
int pos = mPlayer.getCurrentPosition();
pos += ; // milliseconds
mPlayer.seekTo(pos);
setProgress();
show(sDefaultTimeout);
}
};
public void seekTo(int pos){
mPlayer.seekTo(pos);
setProgress();
show(sDefaultTimeout);
}
private void installPrevNextListeners() {
if (mNextButton != null) {
mNextButton.setOnClickListener(mNextListener);
mNextButton.setEnabled(mNextListener != null);
}
if (mPrevButton != null) {
mPrevButton.setOnClickListener(mPrevListener);
mPrevButton.setEnabled(mPrevListener != null);
}
}
public void setPrevNextListeners(OnClickListener next,
OnClickListener prev) {
mNextListener = next;
mPrevListener = prev;
mListenersSet = true;
if (mRoot != null) {
installPrevNextListeners();
if (mNextButton != null && !mFromXml) {
mNextButton.setVisibility(View.VISIBLE);
}
if (mPrevButton != null && !mFromXml) {
mPrevButton.setVisibility(View.VISIBLE);
}
}
}
}
源碼位址:http://download.csdn.net/detail/paddyy/9414789