OSDN Git Service

New capture animation
authorMichael Kolb <kolby@google.com>
Mon, 22 Apr 2013 17:22:21 +0000 (10:22 -0700)
committerMichael Kolb <kolby@google.com>
Wed, 24 Apr 2013 22:45:53 +0000 (15:45 -0700)
  Bug: 8253060

Match new UX design for capture animation
Custom layout for camera controls

Change-Id: I91875ae1685d52d4f9dbb2e6e9299428a8424766

res/values-land/dimensions.xml
res/values/dimens.xml
src/com/android/camera/ActivityBase.java
src/com/android/camera/CameraActivity.java
src/com/android/camera/CameraScreenNail.java
src/com/android/camera/CaptureAnimManager.java
src/com/android/camera/ShutterButton.java
src/com/android/camera/ui/CameraControls.java

index b5c5ed3..b150179 100644 (file)
@@ -16,4 +16,5 @@
 <resources>
     <!-- for manage cache bar -->
     <dimen name="manage_cache_bottom_height">39dp</dimen>
+    <dimen name="capture_margin_top">8dip</dimen>
 </resources>
index 2fcbe7c..5719416 100644 (file)
@@ -97,4 +97,7 @@
     <dimen name="size_preview">600dip</dimen>
     <dimen name="navigation_bar_height">48dip</dimen>
     <dimen name="navigation_bar_width">42dip</dimen>
+    <dimen name="capture_size">48dip</dimen>
+    <dimen name="capture_margin_right">16dip</dimen>
+    <dimen name="capture_margin_top">16dip</dimen>
 </resources>
index dc866f0..d2a4be5 100644 (file)
@@ -558,7 +558,7 @@ public abstract class ActivityBase extends AbstractGalleryActivity
         public ScreenNail attachScreenNail() {
             if (mCameraScreenNail == null) {
                 if (ApiHelper.HAS_SURFACE_TEXTURE) {
-                    mCameraScreenNail = new CameraScreenNail(this);
+                    mCameraScreenNail = new CameraScreenNail(this, getResources());
                 } else {
                     Bitmap b = BitmapFactory.decodeResource(getResources(),
                             R.drawable.wallpaper_picker_preview);
index a332230..5ba769a 100644 (file)
@@ -31,17 +31,14 @@ import android.os.IBinder;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.view.KeyEvent;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.OrientationEventListener;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 
 import com.android.camera.ui.CameraSwitcher;
-import com.android.camera.ui.RotatableLayout;
 import com.android.gallery3d.R;
 import com.android.gallery3d.app.PhotoPage;
 import com.android.gallery3d.common.ApiHelper;
index d531f4a..c5bee2e 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.camera;
 
 import android.annotation.TargetApi;
+import android.content.res.Resources;
 import android.graphics.SurfaceTexture;
 import android.opengl.Matrix;
 import android.util.Log;
@@ -111,8 +112,9 @@ public class CameraScreenNail extends SurfaceTextureScreenNail {
         boolean requiresSurfaceTexture();
     }
 
-    public CameraScreenNail(Listener listener) {
+    public CameraScreenNail(Listener listener, Resources res) {
         mListener = listener;
+        mCaptureAnimManager.setResources(res);
     }
 
     public void setFullScreen(boolean full) {
@@ -386,7 +388,8 @@ public class CameraScreenNail extends SurfaceTextureScreenNail {
                         // Skip the animation if no longer in full screen mode
                         drawn = false;
                     } else {
-                        drawn = mCaptureAnimManager.drawAnimation(canvas, this, mAnimTexture);
+                        drawn = mCaptureAnimManager.drawAnimation(canvas, this, mAnimTexture,
+                                x, y, width, height);
                     }
                 } else {
                     drawn = mSwitchAnimManager.drawAnimation(canvas, x, y,
index ec38290..b820ac9 100644 (file)
 
 package com.android.camera;
 
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
+import com.android.gallery3d.R;
 import com.android.gallery3d.glrenderer.GLCanvas;
 import com.android.gallery3d.glrenderer.RawTexture;
 
@@ -45,7 +48,7 @@ public class CaptureAnimManager {
 
     private final Interpolator mSlideInterpolator = new DecelerateInterpolator();
 
-    private int mAnimOrientation;  // Could be 0, 90, 180 or 270 degrees.
+    private volatile int mAnimOrientation;  // Could be 0, 90, 180 or 270 degrees.
     private long mAnimStartTime;  // milliseconds.
     private float mX;  // The center of the whole view including preview and review.
     private float mY;
@@ -58,7 +61,12 @@ public class CaptureAnimManager {
     private int mHoldW;
     private int mHoldH;
 
-    private int mOffset = 80;
+    private int mOffset;
+
+    private int mMarginRight;
+    private int mMarginTop;
+    private int mSize;
+    private Resources mResources;
 
     /* preview: camera preview view.
      * review: view of picture just taken.
@@ -67,6 +75,10 @@ public class CaptureAnimManager {
 
     }
 
+    public void setResources(Resources res) {
+        mResources = res;
+    }
+
     public void setOrientation(int displayRotation) {
         mAnimOrientation = (360 - displayRotation) % 360;
     }
@@ -90,36 +102,45 @@ public class CaptureAnimManager {
     // x, y, w and h: the rectangle area where the animation takes place.
     public void startAnimation(int x, int y, int w, int h) {
         mAnimStartTime = SystemClock.uptimeMillis();
+        setAnimationGeometry(x, y, w, h);
+    }
+
+    private void setAnimationGeometry(int x, int y, int w, int h) {
+        mMarginRight = mResources.getDimensionPixelSize(R.dimen.capture_margin_right);
+        mMarginTop = mResources.getDimensionPixelSize(R.dimen.capture_margin_top);
+        mSize = mResources.getDimensionPixelSize(R.dimen.capture_size);
+        mOffset = mMarginRight + mSize;
         // Set the views to the initial positions.
         mDrawWidth = w;
         mDrawHeight = h;
         mX = x;
         mY = y;
-        mHoldW = (int) (mDrawWidth * 0.7f);
-        mHoldH = (int) (mDrawHeight * 0.7f);
+        mHoldW = mSize;
+        mHoldH = mSize;
         switch (mAnimOrientation) {
             case 0:  // Preview is on the left.
-                mHoldX = x + w - mOffset;
-                mHoldY = y + (mDrawHeight - mHoldH) / 2;
+                mHoldX = x + w - mMarginRight - mSize;
+                mHoldY = y + mMarginTop;
                 break;
             case 90:  // Preview is below.
-                mHoldX = x + (mDrawWidth - mHoldW + 1) / 2;
-                mHoldY = y + mOffset- mHoldH;
+                mHoldX = x + mMarginTop;
+                mHoldY = y + mMarginRight + mSize;
                 break;
             case 180:  // Preview on the right.
-                mHoldX = x - w + mOffset;
-                mHoldY = y + (mDrawHeight -  mHoldH) / 2;
+                mHoldX = x + mMarginRight;
+                mHoldY = y + h - mMarginTop - mSize;
                 break;
             case 270:  // Preview is above.
-                mHoldX = x + (mDrawWidth - mHoldW + 1) / 2;
-                mHoldY = y + h - mOffset;
+                mHoldX = x + w - mMarginTop - mSize;
+                mHoldY = y + h - mMarginRight - mSize;
                 break;
         }
     }
 
     // Returns true if the animation has been drawn.
     public boolean drawAnimation(GLCanvas canvas, CameraScreenNail preview,
-                RawTexture review) {
+                RawTexture review, int lx, int ly, int lw, int lh) {
+        setAnimationGeometry(lx, ly, lw, lh);
         long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime;
         // Check if the animation is over
         if (mAnimType == ANIM_SLIDE && timeDiff > TIME_SLIDE2 - TIME_HOLD) return false;
index 228fc51..a1bbb1a 100755 (executable)
 package com.android.camera;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.camera.ui.RotatableLayout;
-
 /**
  * A button designed to be used for the on-screen shutter button.
  * It's currently an {@code ImageView} that can call a delegate when the
index a7d1f21..b5de4ea 100644 (file)
@@ -19,17 +19,26 @@ package com.android.camera.ui;
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
-import android.widget.FrameLayout.LayoutParams;
+import android.widget.FrameLayout;
 
 import com.android.camera.Util;
 import com.android.gallery3d.R;
 
-public class CameraControls extends RotatableLayout
-{
+public class CameraControls extends RotatableLayout {
+
+    private static final String TAG = "CAM_Controls";
+
     private View mBackgroundView;
+    private View mShutter;
+    private View mSwitcher;
+    private View mMenu;
+    private View mIndicators;
+
     public CameraControls(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -48,6 +57,147 @@ public class CameraControls extends RotatableLayout
     public void onFinishInflate() {
         super.onFinishInflate();
         mBackgroundView = findViewById(R.id.blocker);
+        mSwitcher = findViewById(R.id.camera_switcher);
+        mShutter = findViewById(R.id.shutter_button);
+        mMenu = findViewById(R.id.menu);
+        mIndicators = findViewById(R.id.on_screen_indicators);
+    }
+
+    @Override
+    public void onLayout(boolean changed, int l, int t, int r, int b) {
+        int orientation = getResources().getConfiguration().orientation;
+        int rotation = Util.getDisplayRotation((Activity) getContext());
+        rotation = correctRotation(rotation, orientation);
+        super.onLayout(changed, l, t, r, b);
+        Rect shutter = new Rect();
+        center(mShutter, l, t, r, b, orientation, rotation, shutter);
+        center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect());
+        toLeft(mSwitcher, l, t, r, b, orientation, rotation, shutter);
+        toRight(mMenu, l, t, r, b, orientation, rotation, shutter);
+        toRight(mIndicators, l, t, r, b, orientation, rotation, shutter);
+    }
+
+    private int correctRotation(int rotation, int orientation) {
+        // all the layout code assumes camera device orientation to be portrait
+        // adjust rotation for landscape
+        int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT
+                : Configuration.ORIENTATION_LANDSCAPE;
+        if (camOrientation != orientation) {
+            return (rotation + 90) % 360;
+        }
+        return rotation;
+    }
+    private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) {
+        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
+        int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
+        int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
+        switch (rotation) {
+        case 0:
+            // phone portrait; controls bottom
+            result.left = (r - l) / 2 - tw / 2 + lp.leftMargin;
+            result.right = (r - l) / 2 + tw / 2 - lp.rightMargin;
+            result.bottom = b - lp.bottomMargin;
+            result.top = b - th + lp.topMargin;
+            break;
+        case 90:
+            // phone landscape: controls right
+            result.right = r - lp.rightMargin;
+            result.left = r - tw + lp.leftMargin;
+            result.top = (b - t) / 2 - th / 2 + lp.topMargin;
+            result.bottom = (b - t) / 2 + th / 2 - lp.bottomMargin;
+            break;
+        case 180:
+            // phone upside down: controls top
+            result.left = (r - l) / 2 - tw / 2 + lp.leftMargin;
+            result.right = (r - l) / 2 + tw / 2 - lp.rightMargin;
+            result.top = t + lp.topMargin;
+            result.bottom = t + th - lp.bottomMargin;
+            break;
+        case 270:
+            // reverse landscape: controls left
+            result.left = l + lp.leftMargin;
+            result.right = l + tw - lp.rightMargin;
+            result.top = (b - t) / 2 - th / 2 + lp.topMargin;
+            result.bottom = (b - t) / 2 + th / 2 - lp.bottomMargin;
+            break;
+        }
+        v.layout(result.left, result.top, result.right, result.bottom);
+    }
+
+    private void toLeft(View v, int l, int t, int r, int b, int orientation, int rotation, Rect anchor) {
+        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
+        int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
+        int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
+        Rect result = new Rect();
+        switch (rotation) {
+        case 0:
+            // portrait, to left of anchor at bottom
+            result.right = anchor.left - lp.rightMargin;
+            result.left = anchor.left - tw + lp.leftMargin;
+            result.bottom = b - lp.bottomMargin;
+            result.top = b - th + lp.topMargin;
+            break;
+        case 90:
+            // phone landscape: below anchor on right
+            result.right = r - lp.rightMargin;
+            result.left = r - tw + lp.leftMargin;
+            result.top = anchor.bottom + lp.topMargin;
+            result.bottom = anchor.bottom + th - lp.bottomMargin;
+            break;
+        case 180:
+            // phone upside down: right of anchor at top
+            result.left = anchor.right + lp.leftMargin;
+            result.right = anchor.right + tw - lp.rightMargin;
+            result.top = t + lp.topMargin;
+            result.bottom = t + th - lp.bottomMargin;
+            break;
+        case 270:
+            // reverse landscape: above anchor on left
+            result.left = l + lp.leftMargin;
+            result.right = l + tw - lp.rightMargin;
+            result.bottom = anchor.top - lp.bottomMargin;
+            result.top = anchor.top - th + lp.topMargin;
+            break;
+        }
+        v.layout(result.left, result.top, result.right, result.bottom);
+    }
+
+    private void toRight(View v, int l, int t, int r, int b, int orientation, int rotation, Rect anchor) {
+        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
+        int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
+        int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
+        Rect result = new Rect();
+        switch (rotation) {
+        case 0:
+            // portrait, right of anchor at bottom
+            result.left = anchor.right + lp.leftMargin;
+            result.right = anchor.right + tw - lp.rightMargin;
+            result.bottom = b - lp.bottomMargin;
+            result.top = b - th + lp.topMargin;
+            break;
+        case 90:
+            // phone landscape: above anchor on right
+            result.right = r - lp.rightMargin;
+            result.left = result.right - tw + lp.leftMargin;
+            result.bottom = anchor.top - lp.bottomMargin;
+            result.top = anchor.top - th + lp.topMargin;
+            break;
+        case 180:
+            // phone upside down: left of anchor at top
+            result.right = anchor.left - lp.rightMargin;
+            result.left = anchor.left - tw + lp.leftMargin;
+            result.top = t + lp.topMargin;
+            result.bottom = t + th - lp.bottomMargin;
+            break;
+        case 270:
+            // reverse landscape: below anchor on left
+            result.left = l + lp.leftMargin;
+            result.right = l + tw - lp.rightMargin;
+            result.top = anchor.bottom + lp.topMargin;
+            result.bottom = anchor.bottom + th - lp.bottomMargin;
+            break;
+        }
+        v.layout(result.left, result.top, result.right, result.bottom);
     }
 
     // In reverse landscape and reverse portrait, camera controls will be laid out
@@ -80,4 +230,5 @@ public class CameraControls extends RotatableLayout
         }
         mBackgroundView.setBackgroundResource(R.drawable.switcher_bg);
     }
+
 }