Support for rotation lock in video recording hints
Bug: 13545160
Change-Id: I73c20e5a6701cc9b89ce6871b6541320fe7317e1
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 7d73246..bb3125d 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -475,6 +475,7 @@
if (mOrientation != newOrientation) {
mOrientation = newOrientation;
}
+ mUI.onOrientationChanged(orientation);
}
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 79b8ccf..161e051 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -33,6 +33,7 @@
import com.android.camera.ui.PreviewOverlay;
import com.android.camera.ui.PreviewStatusListener;
import com.android.camera.ui.RotateLayout;
+import com.android.camera.widget.VideoRecordingHints;
import com.android.camera2.R;
import java.util.List;
@@ -49,7 +50,7 @@
// An review image having same size as preview. It is displayed when
// recording is stopped in capture intent.
private ImageView mReviewImage;
- private View mVideoHints;
+ private VideoRecordingHints mVideoHints;
private TextView mRecordingTimeView;
private LinearLayout mLabelsLinearLayout;
private View mTimeLapseLabel;
@@ -108,7 +109,7 @@
initializeMiscControls();
mAnimationManager = new AnimationManager();
mFocusUI = (FocusOverlay) mRootView.findViewById(R.id.focus_overlay);
- mVideoHints = mRootView.findViewById(R.id.video_shooting_hints);
+ mVideoHints = (VideoRecordingHints) mRootView.findViewById(R.id.video_shooting_hints);
}
public void setPreviewSize(int width, int height) {
@@ -276,6 +277,10 @@
return new Point(mRootView.getMeasuredWidth(), mRootView.getMeasuredHeight());
}
+ public void onOrientationChanged(int orientation) {
+ mVideoHints.onOrientationChanged(orientation);
+ }
+
private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener {
@Override
public void onZoomValueChanged(int index) {
diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java
deleted file mode 100644
index e05b0cb..0000000
--- a/src/com/android/camera/ui/CameraControls.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-public class CameraControls extends RotatableLayout {
-
- public CameraControls(Context context, AttributeSet attrs) {
- super(context, attrs);
- setMeasureAllChildren(true);
- }
-
- public CameraControls(Context context) {
- super(context);
- setMeasureAllChildren(true);
- }
-
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- }
-}
diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java
deleted file mode 100644
index 85948c6..0000000
--- a/src/com/android/camera/ui/RotatableLayout.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import com.android.camera.debug.Log;
-import com.android.camera.util.CameraUtil;
-
-/* RotatableLayout rotates itself as well as all its children when orientation
- * changes. Specifically, when going from portrait to landscape, camera
- * controls move from the bottom of the screen to right side of the screen
- * (i.e. counter clockwise). Similarly, when the screen changes to portrait, we
- * need to move the controls from right side to the bottom of the screen, which
- * is a clockwise rotation.
- */
-
-public class RotatableLayout extends FrameLayout {
-
- private static final Log.Tag TAG = new Log.Tag("RotatableLayout");
- private static final int UNKOWN_ORIENTATION = -1;
- // Initial orientation of the layout (ORIENTATION_PORTRAIT, or ORIENTATION_LANDSCAPE)
- private int mInitialOrientation;
- private int mPrevRotation = UNKOWN_ORIENTATION;
- private boolean mIsDefaultToPortrait = false;
-
- public RotatableLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- public RotatableLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public RotatableLayout(Context context) {
- super(context);
- init();
- }
-
- private void init() {
- mInitialOrientation = getResources().getConfiguration().orientation;
- }
-
- @Override
- public void onAttachedToWindow() {
- // Before the first time this view is attached to window, device rotation
- // will not trigger onConfigurationChanged callback. So in the first run
- // we need to rotate the view if necessary. After that, onConfigurationChanged
- // call will track all the subsequent device rotation.
- if (mPrevRotation == UNKOWN_ORIENTATION) {
- mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait((Activity) getContext());
- if (mIsDefaultToPortrait) {
- // Natural orientation for tablet is landscape
- mPrevRotation = mInitialOrientation == Configuration.ORIENTATION_PORTRAIT ?
- 0 : 90;
- } else {
- // When tablet orientation is 0 or 270 (i.e. getUnifiedOrientation
- // = 0 or 90), we load the layout resource without any rotation.
- mPrevRotation = mInitialOrientation == Configuration.ORIENTATION_LANDSCAPE ?
- 0 : 270;
- }
-
- // check if there is any rotation before the view is attached to window
- rotateIfNeeded();
- }
- }
-
- private void rotateIfNeeded() {
- if (mPrevRotation == UNKOWN_ORIENTATION) {
- return;
- }
- int rotation = CameraUtil.getDisplayRotation((Activity) getContext());
- int diff = (rotation - mPrevRotation + 360) % 360;
- if ( diff == 0) {
- // No rotation
- return;
- } else if (diff == 180) {
- // 180-degree rotation
- mPrevRotation = rotation;
- flipChildren();
- return;
- }
- // 90 or 270-degree rotation
- boolean clockwise = isClockWiseRotation(mPrevRotation, rotation);
- mPrevRotation = rotation;
- rotateLayout(clockwise);
- }
-
- protected int getUnifiedRotation() {
- // all the layout code assumes camera device orientation to be portrait
- // adjust rotation for landscape
- int rotation = CameraUtil.getDisplayRotation((Activity) getContext());
- if (!mIsDefaultToPortrait) {
- return (rotation + 90) % 360;
- }
- return rotation;
- }
-
- public void checkLayoutFlip() {
- int currentRotation = CameraUtil.getDisplayRotation((Activity) getContext());
- if ((currentRotation - mPrevRotation + 360) % 360 == 180) {
- mPrevRotation = currentRotation;
- flipChildren();
- requestLayout();
- }
- }
-
- @Override
- public void onWindowVisibilityChanged(int visibility) {
- if (visibility == View.VISIBLE) {
- // Make sure when coming back from onPause, the layout is rotated correctly
- checkLayoutFlip();
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
- rotateIfNeeded();
- }
-
- protected void rotateLayout(boolean clockwise) {
- // Change the size of the layout
- ViewGroup.LayoutParams lp = getLayoutParams();
- int width = lp.width;
- int height = lp.height;
- lp.height = width;
- lp.width = height;
- setLayoutParams(lp);
-
- // rotate all the children
- rotateChildren(clockwise);
- }
-
- protected void rotateChildren(boolean clockwise) {
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- rotate(child, clockwise);
- }
- }
-
- protected void flipChildren() {
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- flip(child);
- }
- }
-
- public static boolean isClockWiseRotation(int prevRotation, int currentRotation) {
- if (prevRotation == (currentRotation + 90) % 360) {
- return true;
- }
- return false;
- }
-
- public static void rotate(View view, boolean isClockwise) {
- if (isClockwise) {
- rotateClockwise(view);
- } else {
- rotateCounterClockwise(view);
- }
- }
-
- private static boolean contains(int value, int mask) {
- return (value & mask) == mask;
- }
-
- public static void rotateClockwise(View view) {
- if (view == null) return;
- LayoutParams lp = (LayoutParams) view.getLayoutParams();
- int gravity = lp.gravity;
- int ngravity = 0;
- // rotate gravity
- if (contains(gravity, Gravity.LEFT)) {
- ngravity |= Gravity.TOP;
- }
- if (contains(gravity, Gravity.RIGHT)) {
- ngravity |= Gravity.BOTTOM;
- }
- if (contains(gravity, Gravity.TOP)) {
- ngravity |= Gravity.RIGHT;
- }
- if (contains(gravity, Gravity.BOTTOM)) {
- ngravity |= Gravity.LEFT;
- }
- if (contains(gravity, Gravity.CENTER)) {
- ngravity |= Gravity.CENTER;
- }
- if (contains(gravity, Gravity.CENTER_HORIZONTAL)) {
- ngravity |= Gravity.CENTER_VERTICAL;
- }
- if (contains(gravity, Gravity.CENTER_VERTICAL)) {
- ngravity |= Gravity.CENTER_HORIZONTAL;
- }
- lp.gravity = ngravity;
- int ml = lp.leftMargin;
- int mr = lp.rightMargin;
- int mt = lp.topMargin;
- int mb = lp.bottomMargin;
- lp.leftMargin = mb;
- lp.rightMargin = mt;
- lp.topMargin = ml;
- lp.bottomMargin = mr;
- int width = lp.width;
- int height = lp.height;
- lp.width = height;
- lp.height = width;
- view.setLayoutParams(lp);
- }
-
- public static void rotateCounterClockwise(View view) {
- if (view == null) return;
- LayoutParams lp = (LayoutParams) view.getLayoutParams();
- int gravity = lp.gravity;
- int ngravity = 0;
- // change gravity
- if (contains(gravity, Gravity.RIGHT)) {
- ngravity |= Gravity.TOP;
- }
- if (contains(gravity, Gravity.LEFT)) {
- ngravity |= Gravity.BOTTOM;
- }
- if (contains(gravity, Gravity.TOP)) {
- ngravity |= Gravity.LEFT;
- }
- if (contains(gravity, Gravity.BOTTOM)) {
- ngravity |= Gravity.RIGHT;
- }
- if (contains(gravity, Gravity.CENTER)) {
- ngravity |= Gravity.CENTER;
- }
- if (contains(gravity, Gravity.CENTER_HORIZONTAL)) {
- ngravity |= Gravity.CENTER_VERTICAL;
- }
- if (contains(gravity, Gravity.CENTER_VERTICAL)) {
- ngravity |= Gravity.CENTER_HORIZONTAL;
- }
- lp.gravity = ngravity;
- int ml = lp.leftMargin;
- int mr = lp.rightMargin;
- int mt = lp.topMargin;
- int mb = lp.bottomMargin;
- lp.leftMargin = mt;
- lp.rightMargin = mb;
- lp.topMargin = mr;
- lp.bottomMargin = ml;
- int width = lp.width;
- int height = lp.height;
- lp.width = height;
- lp.height = width;
- view.setLayoutParams(lp);
- }
-
- // Rotate a given view 180 degrees
- public static void flip(View view) {
- rotateClockwise(view);
- rotateClockwise(view);
- }
-}
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 4aafead..a633905 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -410,11 +410,12 @@
/**
* Calculate the default orientation of the device based on the width and
* height of the display when rotation = 0 (i.e. natural width and height)
- * @param activity the activity context
+ * @param context current context
* @return whether the default orientation of the device is portrait
*/
- public static boolean isDefaultToPortrait(Activity activity) {
- Display currentDisplay = activity.getWindowManager().getDefaultDisplay();
+ public static boolean isDefaultToPortrait(Context context) {
+ Display currentDisplay = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay();
Point displaySize = new Point();
currentDisplay.getSize(displaySize);
int orientation = currentDisplay.getRotation();
diff --git a/src/com/android/camera/widget/VideoRecordingHints.java b/src/com/android/camera/widget/VideoRecordingHints.java
index 294ec3c..c931dfb 100644
--- a/src/com/android/camera/widget/VideoRecordingHints.java
+++ b/src/com/android/camera/widget/VideoRecordingHints.java
@@ -20,12 +20,13 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.OrientationEventListener;
import android.view.View;
+import com.android.camera.util.CameraUtil;
import com.android.camera2.R;
/**
@@ -48,12 +49,14 @@
private final Drawable mRotateArrows;
private final Drawable mPhoneGraphic;
private final int mPhoneGraphicHalfHeight;
+ private final boolean mIsDefaultToPortrait;
private float mRotation = INITIAL_ROTATION;
private final ValueAnimator mRotationAnimation;
private final ObjectAnimator mAlphaAnimator;
private boolean mIsInLandscape = false;
private int mCenterX = UNSET;
private int mCenterY = UNSET;
+ private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
public VideoRecordingHints(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -135,7 +138,7 @@
// Do nothing.
}
});
-
+ mIsDefaultToPortrait = CameraUtil.isDefaultToPortrait(context);
}
/**
@@ -154,8 +157,7 @@
@Override
public void onVisibilityChanged(View v, int visibility) {
super.onVisibilityChanged(v, visibility);
- if (getVisibility() == VISIBLE && getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_PORTRAIT) {
+ if (getVisibility() == VISIBLE && !isInLandscape()) {
continueRotationAnimation();
} else if (getVisibility() != VISIBLE) {
mRotationAnimation.cancel();
@@ -164,17 +166,6 @@
}
@Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (getVisibility() == VISIBLE && getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_PORTRAIT) {
- continueRotationAnimation();
- }
- mIsInLandscape = getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE;
- }
-
- @Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// Center drawables in the layout
@@ -188,24 +179,6 @@
}
@Override
- public void onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
- if (getVisibility() == VISIBLE) {
- if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
- mRotationAnimation.cancel();
- // Start fading out.
- if (mAlphaAnimator.isRunning()) {
- return;
- }
- mAlphaAnimator.start();
- } else {
- continueRotationAnimation();
- }
- }
- mIsInLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE;
- }
-
- @Override
public void draw(Canvas canvas) {
super.draw(canvas);
// Don't draw anything after the fade-out animation in landscape.
@@ -226,4 +199,42 @@
}
}
+ /**
+ * Handles orientation change by starting/stopping the video hint based on the
+ * new orientation.
+ */
+ public void onOrientationChanged(int orientation) {
+ if (mLastOrientation == orientation) {
+ return;
+ }
+ mLastOrientation = orientation;
+ if (mLastOrientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
+ return;
+ }
+
+ mIsInLandscape = isInLandscape();
+ if (getVisibility() == VISIBLE) {
+ if (mIsInLandscape) {
+ // Landscape.
+ mRotationAnimation.cancel();
+ // Start fading out.
+ if (mAlphaAnimator.isRunning()) {
+ return;
+ }
+ mAlphaAnimator.start();
+ } else {
+ // Portrait.
+ continueRotationAnimation();
+ }
+ }
+ }
+
+ /**
+ * Returns whether the device is in landscape based on the natural orientation
+ * and rotation from natural orientation.
+ */
+ private boolean isInLandscape() {
+ return (mLastOrientation % 180 == 90 && mIsDefaultToPortrait)
+ || (mLastOrientation % 180 == 0 && !mIsDefaultToPortrait);
+ }
}