From 705604dfd85362a4b98887b2b1a173e6658853d8 Mon Sep 17 00:00:00 2001 From: Michael Kolb Date: Mon, 22 Apr 2013 10:22:21 -0700 Subject: New capture animation Bug: 8253060 Match new UX design for capture animation Custom layout for camera controls Change-Id: I91875ae1685d52d4f9dbb2e6e9299428a8424766 --- src/com/android/camera/ActivityBase.java | 2 +- src/com/android/camera/CameraActivity.java | 3 - src/com/android/camera/CameraScreenNail.java | 7 +- src/com/android/camera/CaptureAnimManager.java | 47 ++++++-- src/com/android/camera/ShutterButton.java | 3 - src/com/android/camera/ui/CameraControls.java | 157 ++++++++++++++++++++++++- 6 files changed, 194 insertions(+), 25 deletions(-) diff --git a/src/com/android/camera/ActivityBase.java b/src/com/android/camera/ActivityBase.java index dc866f0e5..d2a4be58a 100644 --- a/src/com/android/camera/ActivityBase.java +++ b/src/com/android/camera/ActivityBase.java @@ -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); diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index a33223083..5ba769a62 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -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; diff --git a/src/com/android/camera/CameraScreenNail.java b/src/com/android/camera/CameraScreenNail.java index d531f4adf..c5bee2e8e 100644 --- a/src/com/android/camera/CameraScreenNail.java +++ b/src/com/android/camera/CameraScreenNail.java @@ -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, diff --git a/src/com/android/camera/CaptureAnimManager.java b/src/com/android/camera/CaptureAnimManager.java index ec38290b3..b820ac9fa 100644 --- a/src/com/android/camera/CaptureAnimManager.java +++ b/src/com/android/camera/CaptureAnimManager.java @@ -16,11 +16,14 @@ 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; diff --git a/src/com/android/camera/ShutterButton.java b/src/com/android/camera/ShutterButton.java index 228fc51a3..a1bbb1a0d 100755 --- a/src/com/android/camera/ShutterButton.java +++ b/src/com/android/camera/ShutterButton.java @@ -17,14 +17,11 @@ 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 diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java index a7d1f215e..b5de4ea9a 100644 --- a/src/com/android/camera/ui/CameraControls.java +++ b/src/com/android/camera/ui/CameraControls.java @@ -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); } + } -- cgit v1.2.3