From 00bb8e439e33848d679a4404c203af9ed1a06a19 Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Wed, 23 May 2012 15:47:36 -0700 Subject: [PATCH] Add back the background when we show the action bar This change fix the following UI issues: 1. We add a black backgorund when ActionBar shows and remove it when we hide the action bar. 2. Make the postion of video stable when opening 3. Prevent glitching when opening a video 4. Make it really full-screen. 5. Hide ControlOverlay at begining. bug:6519765 bug:6491674 Change-Id: I3ab033642df2c4a158b99385b02e3e967eebeabd --- res/layout/movie_view.xml | 10 ++-- src/com/android/gallery3d/app/MovieActivity.java | 4 +- .../gallery3d/app/MovieControllerOverlay.java | 62 ++++++++++++++-------- src/com/android/gallery3d/app/MoviePlayer.java | 49 ++++++++++++++--- 4 files changed, 92 insertions(+), 33 deletions(-) diff --git a/res/layout/movie_view.xml b/res/layout/movie_view.xml index 4e645cf09..75b8dfd4f 100644 --- a/res/layout/movie_view.xml +++ b/res/layout/movie_view.xml @@ -15,13 +15,13 @@ --> - + android:id="@+id/movie_view_root" + android:background="@android:color/black" + android:layout_width="match_parent" + android:layout_height="match_parent"> - diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java index b0e53c405..78fe1ee78 100644 --- a/src/com/android/gallery3d/app/MovieActivity.java +++ b/src/com/android/gallery3d/app/MovieActivity.java @@ -68,7 +68,9 @@ public class MovieActivity extends Activity { setContentView(R.layout.movie_view); View rootView = findViewById(R.id.movie_view_root); - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); Intent intent = getIntent(); initializeActionBar(intent); mFinishOnCompletion = intent.getBooleanExtra( diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java index ae9f085a1..f2c9e05dd 100644 --- a/src/com/android/gallery3d/app/MovieControllerOverlay.java +++ b/src/com/android/gallery3d/app/MovieControllerOverlay.java @@ -17,6 +17,7 @@ package com.android.gallery3d.app; import android.content.Context; +import android.graphics.Rect; import android.os.Handler; import android.view.Gravity; import android.view.KeyEvent; @@ -227,6 +228,7 @@ public class MovieControllerOverlay extends FrameLayout implements } private void startHiding() { + startHideAnimation(background); startHideAnimation(timeBar); startHideAnimation(playPauseReplayView); } @@ -302,36 +304,54 @@ public class MovieControllerOverlay extends FrameLayout implements return true; } + // The paddings of 4 sides which covered by system components. E.g. + // +-----------------+\ + // | Action Bar | insets.top + // +-----------------+/ + // | | + // | Content Area | insets.right = insets.left = 0 + // | | + // +-----------------+\ + // | Navigation Bar | insets.bottom + // +-----------------+/ + // Please see View.fitSystemWindows() for more details. + private final Rect mWindowInsets = new Rect(); + @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int bw; - int bh; - int y; - int h = b - t; - int w = r - l; - boolean error = errorView.getVisibility() == View.VISIBLE; + protected boolean fitSystemWindows(Rect insets) { + // We don't set the paddings of this View, otherwise, + // the content will get cropped outside window + mWindowInsets.set(insets); + return true; + } - bw = timeBar.getBarHeight(); - bh = bw; - y = b - bh; + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + Rect insets = mWindowInsets; + int pl = insets.left; // the left paddings + int pr = insets.right; + int pt = insets.top; + int pb = insets.bottom; + + int h = bottom - top; + int w = right - left; + boolean error = errorView.getVisibility() == View.VISIBLE; - background.layout(l, y, r, b); + int y = h - pb; + // Put both TimeBar and Background just above the bottom system component. + // But extend the background to the width of the screen, since we don't + // care if it will be covered by a system component and it looks better. + background.layout(0, y - timeBar.getBarHeight(), w, y); + timeBar.layout(pl, y - timeBar.getPreferredHeight(), w - pr, y); - timeBar.layout(l, b - timeBar.getPreferredHeight(), r, b); // Needed, otherwise the framework will not re-layout in case only the padding is changed timeBar.requestLayout(); - // play pause / next / previous buttons - int cx = l + w / 2; // center x - int playbackButtonsCenterline = t + h / 2; - bw = playPauseReplayView.getMeasuredWidth(); - bh = playPauseReplayView.getMeasuredHeight(); - playPauseReplayView.layout( - cx - bw / 2, playbackButtonsCenterline - bh / 2, cx + bw / 2, - playbackButtonsCenterline + bh / 2); + // Put the play/pause/next/ previous button in the center of the screen + layoutCenteredView(playPauseReplayView, 0, 0, w, h); if (mainView != null) { - layoutCenteredView(mainView, l, t, r, b); + layoutCenteredView(mainView, 0, 0, w, h); } } diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java index 565d2b239..13a77f472 100644 --- a/src/com/android/gallery3d/app/MoviePlayer.java +++ b/src/com/android/gallery3d/app/MoviePlayer.java @@ -16,7 +16,6 @@ package com.android.gallery3d.app; -import android.app.ActionBar; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -25,6 +24,7 @@ import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.Color; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; @@ -60,18 +60,20 @@ public class MoviePlayer implements private static final String CMDNAME = "command"; private static final String CMDPAUSE = "pause"; + private static final long BLACK_TIMEOUT = 500; + // If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing. // Otherwise, we pause the player. private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins private Context mContext; private final VideoView mVideoView; + private final View mRootView; private final Bookmarker mBookmarker; private final Uri mUri; private final Handler mHandler = new Handler(); private final AudioBecomingNoisyReceiver mAudioBecomingNoisyReceiver; - private final ActionBar mActionBar; - private final ControllerOverlay mController; + private final MovieControllerOverlay mController; private long mResumeableTime = Long.MAX_VALUE; private int mVideoPosition = 0; @@ -98,6 +100,13 @@ public class MoviePlayer implements } }; + private final Runnable mRemoveBackground = new Runnable() { + @Override + public void run() { + mRootView.setBackground(null); + } + }; + private final Runnable mProgressChecker = new Runnable() { @Override public void run() { @@ -106,12 +115,12 @@ public class MoviePlayer implements } }; - public MoviePlayer(View rootView, final MovieActivity movieActivity, Uri videoUri, - Bundle savedInstance, boolean canReplay) { + public MoviePlayer(View rootView, final MovieActivity movieActivity, + Uri videoUri, Bundle savedInstance, boolean canReplay) { mContext = movieActivity.getApplicationContext(); + mRootView = rootView; mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); mBookmarker = new Bookmarker(movieActivity); - mActionBar = movieActivity.getActionBar(); mUri = videoUri; mController = new MovieControllerOverlay(mContext); @@ -123,17 +132,31 @@ public class MoviePlayer implements mVideoView.setOnCompletionListener(this); mVideoView.setVideoURI(mUri); mVideoView.setOnTouchListener(new View.OnTouchListener() { + @Override public boolean onTouch(View v, MotionEvent event) { mController.show(); return true; } }); + // The SurfaceView is transparent before drawing the first frame. + // This makes the UI flashing when open a video. (black -> old screen + // -> video) However, we have no way to know the timing of the first + // frame. So, we hide the VideoView for a while to make sure the + // video has been drawn on it. + mVideoView.postDelayed(new Runnable() { + @Override + public void run() { + mVideoView.setVisibility(View.VISIBLE); + } + }, BLACK_TIMEOUT); + // When the user touches the screen or uses some hard key, the framework // will change system ui visibility from invisible to visible. We show // the media control and enable system UI (e.g. ActionBar) to be visible at this point mVideoView.setOnSystemUiVisibilityChangeListener( new View.OnSystemUiVisibilityChangeListener() { + @Override public void onSystemUiVisibilityChange(int visibility) { int diff = mLastSystemUiVis ^ visibility; mLastSystemUiVis = visibility; @@ -141,6 +164,19 @@ public class MoviePlayer implements && (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { mAllowShowingSystemUI = true; mController.show(); + + // We need to set the background to clear ghosting images + // when ActionBar slides in. However, if we keep the background, + // there will be one additional layer in HW composer, which is bad + // to battery. As a solution, we remove the background when we + // hide the action bar + mHandler.removeCallbacks(mRemoveBackground); + mRootView.setBackgroundColor(Color.BLACK); + } else { + mHandler.removeCallbacks(mRemoveBackground); + + // Wait for the slide out animation, one second should be enough + mHandler.postDelayed(mRemoveBackground, 1000); } } }); @@ -267,6 +303,7 @@ public class MoviePlayer implements mHandler.postDelayed(mPlayingChecker, 250); } else { mController.showPlaying(); + mController.hide(); } mVideoView.start(); -- 2.11.0