OSDN Git Service

Add back the background when we show the action bar
authorOwen Lin <owenlin@google.com>
Wed, 23 May 2012 22:47:36 +0000 (15:47 -0700)
committerOwen Lin <owenlin@google.com>
Fri, 25 May 2012 23:02:23 +0000 (16:02 -0700)
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
src/com/android/gallery3d/app/MovieActivity.java
src/com/android/gallery3d/app/MovieControllerOverlay.java
src/com/android/gallery3d/app/MoviePlayer.java

index 4e645cf..75b8dfd 100644 (file)
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/movie_view_root"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
+        android:id="@+id/movie_view_root"
+        android:background="@android:color/black"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
     <VideoView android:id="@+id/surface_view"
+            android:visibility="invisible"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_centerInParent="true" />
-
 </RelativeLayout>
index b0e53c4..78fe1ee 100644 (file)
@@ -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(
index ae9f085..f2c9e05 100644 (file)
@@ -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);
     }
   }
 
index 565d2b2..13a77f4 100644 (file)
@@ -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();