summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoris Liu <tianliu@google.com>2013-12-17 18:41:15 -0800
committerDoris Liu <tianliu@google.com>2013-12-17 23:33:29 -0800
commit70da918464276b110c43868caa272c97baadb89e (patch)
treea5c9b99ca860e3e6be32cd36fefb5fcc5f1e3511
parentdb44ef57cdb576704b1aafb2b81e30bf9ff261ad (diff)
downloadandroid_packages_apps_Camera2-70da918464276b110c43868caa272c97baadb89e.tar.gz
android_packages_apps_Camera2-70da918464276b110c43868caa272c97baadb89e.tar.bz2
android_packages_apps_Camera2-70da918464276b110c43868caa272c97baadb89e.zip
Centralized TextureView transform logic
Automated transform matrix adjustment and bottom bar adjustment for orientation or preview size change. Bug: 12177718 Bug: 12179046 Change-Id: I4cd6fc90bb549774cfd83aaf8ac9654711a5c752
-rw-r--r--res/layout-land/bottom_bar.xml2
-rw-r--r--res/layout-port/bottom_bar.xml2
-rw-r--r--src/com/android/camera/CameraActivity.java11
-rw-r--r--src/com/android/camera/PhotoController.java3
-rw-r--r--src/com/android/camera/PhotoModule.java5
-rw-r--r--src/com/android/camera/PhotoUI.java54
-rw-r--r--src/com/android/camera/TextureViewHelper.java208
-rw-r--r--src/com/android/camera/VideoController.java2
-rw-r--r--src/com/android/camera/VideoModule.java5
-rw-r--r--src/com/android/camera/VideoUI.java55
-rw-r--r--src/com/android/camera/app/AppController.java18
-rw-r--r--src/com/android/camera/app/CameraAppUI.java137
-rw-r--r--src/com/android/camera/ui/BottomBar.java107
-rw-r--r--src/com/android/camera/ui/PreviewStatusListener.java26
14 files changed, 414 insertions, 221 deletions
diff --git a/res/layout-land/bottom_bar.xml b/res/layout-land/bottom_bar.xml
index 1d2ca0b25..e7b44c5ed 100644
--- a/res/layout-land/bottom_bar.xml
+++ b/res/layout-land/bottom_bar.xml
@@ -20,7 +20,7 @@
<com.android.camera.ui.BottomBar
android:id="@+id/bottom_bar"
android:layout_height="match_parent"
- android:layout_width="@dimen/bottom_bar_height_optimal"
+ android:layout_width="match_parent"
android:layout_gravity="right"
android:paddingTop="@dimen/camera_controls_padding_start"
android:paddingBottom="@dimen/camera_controls_padding_end"
diff --git a/res/layout-port/bottom_bar.xml b/res/layout-port/bottom_bar.xml
index 01fe00160..9102bc6b9 100644
--- a/res/layout-port/bottom_bar.xml
+++ b/res/layout-port/bottom_bar.xml
@@ -20,7 +20,7 @@
<com.android.camera.ui.BottomBar
android:id="@+id/bottom_bar"
android:layout_width="match_parent"
- android:layout_height="@dimen/bottom_bar_height_optimal"
+ android:layout_height="match_parent"
android:layout_gravity="bottom"
android:paddingLeft="@dimen/camera_controls_padding_start"
android:paddingRight="@dimen/camera_controls_padding_end"
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 55d1c9021..8579b3d8d 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -32,6 +32,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
+import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
@@ -668,6 +669,16 @@ public class CameraActivity extends Activity
}
@Override
+ public void updatePreviewAspectRatio(float aspectRatio) {
+ mCameraAppUI.updatePreviewAspectRatio(aspectRatio);
+ }
+
+ @Override
+ public void updatePreviewTransform(Matrix matrix) {
+ mCameraAppUI.updatePreviewTransform(matrix);
+ }
+
+ @Override
public void setPreviewStatusListener(PreviewStatusListener previewStatusListener) {
mCameraAppUI.setPreviewStatusListener(previewStatusListener);
}
diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java
index bb80d62fa..1de9d130e 100644
--- a/src/com/android/camera/PhotoController.java
+++ b/src/com/android/camera/PhotoController.java
@@ -55,6 +55,8 @@ public interface PhotoController extends OnShutterButtonListener {
public void onPreviewRectChanged(Rect previewRect);
+ public void updatePreviewAspectRatio(float aspectRatio);
+
public void updateCameraOrientation();
/**
@@ -78,4 +80,5 @@ public interface PhotoController extends OnShutterButtonListener {
* Starts the pre-capture animation.
*/
public void startPreCaptureAnimation();
+
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index c4c7a4ef9..891b814c2 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -517,6 +517,11 @@ public class PhotoModule
mFocusManager.setPreviewRect(previewRect);
}
+ @Override
+ public void updatePreviewAspectRatio(float aspectRatio) {
+ mAppController.updatePreviewAspectRatio(aspectRatio);
+ }
+
private void resetExposureCompensation() {
SettingsManager settingsManager = mActivity.getSettingsManager();
if (settingsManager == null) {
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index dc790ddac..ed15407e3 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -29,13 +29,8 @@ import android.view.MotionEvent;
import android.view.TextureView;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewStub;
-import android.widget.CompoundButton;
-import android.widget.FrameLayout.LayoutParams;
-import android.widget.ImageButton;
-import android.widget.ImageView;
import android.widget.Toast;
import com.android.camera.FocusOverlayManager.FocusUI;
@@ -57,6 +52,7 @@ public class PhotoUI implements
private static final String TAG = "PhotoUI";
private static final int DOWN_SAMPLE_FACTOR = 4;
+ private static final float UNSET = 0f;
private final PreviewOverlay mPreviewOverlay;
private CameraActivity mActivity;
@@ -80,11 +76,9 @@ public class PhotoUI implements
private SurfaceTextureSizeChangedListener mSurfaceTextureSizeListener;
private TextureView mTextureView;
private Matrix mMatrix = null;
- private float mAspectRatio = 4f / 3f;
+ private float mAspectRatio = UNSET;
private final Object mSurfaceTextureLock = new Object();
private BottomBar mBottomBar;
- private final int mBottomBarMinHeight;
- private final int mBottomBarOptimalHeight;
private ButtonManager.ButtonCallback mCameraCallback;
private ButtonManager.ButtonCallback mHdrCallback;
@@ -135,10 +129,19 @@ public class PhotoUI implements
if (mPreviewWidth != width || mPreviewHeight != height) {
mPreviewWidth = width;
mPreviewHeight = height;
- setTransformMatrix(width, height);
}
}
+ @Override
+ public boolean shouldAutoAdjustTransformMatrixOnLayout() {
+ return true;
+ }
+
+ @Override
+ public boolean shouldAutoAdjustBottomBar() {
+ return true;
+ }
+
private class DecodeTask extends AsyncTask<Void, Void, Bitmap> {
private final byte [] mData;
private int mOrientation;
@@ -194,17 +197,8 @@ public class PhotoUI implements
mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
initIndicators();
- mBottomBar = (BottomBar) mRootView.findViewById(R.id.bottom_bar);
- mBottomBarMinHeight = activity.getResources()
- .getDimensionPixelSize(R.dimen.bottom_bar_height_min);
- mBottomBarOptimalHeight = activity.getResources()
- .getDimensionPixelSize(R.dimen.bottom_bar_height_optimal);
-
mSurfaceTexture = mTextureView.getSurfaceTexture();
- if (mSurfaceTexture != null) {
- setTransformMatrix(mTextureView.getWidth(), mTextureView.getHeight());
- }
-
+ mBottomBar = (BottomBar) mRootView.findViewById(R.id.bottom_bar);
mBottomBar.setBackgroundColor(activity.getResources().getColor(R.color.camera_mode_color));
ViewStub faceViewStub = (ViewStub) mRootView
.findViewById(R.id.face_view_stub);
@@ -233,17 +227,10 @@ public class PhotoUI implements
if (mAspectRatio != aspectRatio) {
mAspectRatio = aspectRatio;
// Update transform matrix with the new aspect ratio.
- if (mPreviewWidth != 0 && mPreviewHeight != 0) {
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
- }
+ mController.updatePreviewAspectRatio(mAspectRatio);
}
}
- private void setTransformMatrix(int width, int height) {
- mActivity.getCameraAppUI().adjustPreviewAndBottomBarSize(width, height, mBottomBar,
- mAspectRatio, mBottomBarMinHeight, mBottomBarOptimalHeight);
- }
-
protected Object getSurfaceTextureLock() {
return mSurfaceTextureLock;
}
@@ -254,11 +241,6 @@ public class PhotoUI implements
Log.v(TAG, "SurfaceTexture ready.");
mSurfaceTexture = surface;
mController.onPreviewUIReady();
- // Workaround for b/11168275, see b/10981460 for more details
- if (mPreviewWidth != 0 && mPreviewHeight != 0) {
- // Re-apply transform matrix for new surface texture
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
- }
}
}
@@ -468,14 +450,6 @@ public class PhotoUI implements
return mSurfaceTexture;
}
- public void showPreferencesToast() {
- if (mNotSelectableToast == null) {
- String str = mActivity.getResources().getString(R.string.not_selectable_in_scene_mode);
- mNotSelectableToast = Toast.makeText(mActivity, str, Toast.LENGTH_SHORT);
- }
- mNotSelectableToast.show();
- }
-
public void onPause() {
if (mFaceView != null) mFaceView.clear();
}
diff --git a/src/com/android/camera/TextureViewHelper.java b/src/com/android/camera/TextureViewHelper.java
new file mode 100644
index 000000000..fbd4e7407
--- /dev/null
+++ b/src/com/android/camera/TextureViewHelper.java
@@ -0,0 +1,208 @@
+/*
+ * 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;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+
+import com.android.camera.ui.PreviewStatusListener;
+
+/**
+ * This class aims to automate TextureView transform change and notify listeners
+ * (e.g. bottom bar) of the preview size change.
+ */
+public class TextureViewHelper implements TextureView.SurfaceTextureListener,
+ OnLayoutChangeListener {
+
+ private static final String TAG = "TextureViewHelper";
+ private static final float UNSET = 0f;
+ private TextureView mPreview;
+ private int mWidth = 0;
+ private int mHeight = 0;
+ private float mAspectRatio = UNSET;
+ private boolean mAutoAdjustTransform = true;
+ private TextureView.SurfaceTextureListener mSurfaceTextureListener;
+
+ private PreviewStatusListener.PreviewSizeChangedListener mPreviewSizeChangedListener;
+ private OnLayoutChangeListener mOnLayoutChangeListener = null;
+
+ public TextureViewHelper(TextureView preview) {
+ mPreview = preview;
+ mPreview.addOnLayoutChangeListener(this);
+ mPreview.setSurfaceTextureListener(this);
+ }
+
+ /**
+ * If auto adjust transform is enabled, when there is a layout change, the
+ * transform matrix will be automatically adjusted based on the preview stream
+ * aspect ratio in the new layout.
+ *
+ * @param enable whether or not auto adjustment should be enabled
+ */
+ public void setAutoAdjustTransform(boolean enable) {
+ mAutoAdjustTransform = enable;
+ }
+
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ int width = right - left;
+ int height = bottom - top;
+ if (mWidth != width || mHeight != height) {
+ mWidth = width;
+ mHeight = height;
+ if (mAutoAdjustTransform) {
+ updateTransform();
+ }
+ }
+ if (mOnLayoutChangeListener != null) {
+ mOnLayoutChangeListener.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop,
+ oldRight, oldBottom);
+ }
+ }
+
+ public void updateAspectRatio(float aspectRatio) {
+ if (aspectRatio <= 0) {
+ Log.e(TAG, "Invalid aspect ratio: " + aspectRatio);
+ return;
+ }
+ if (aspectRatio < 1f) {
+ aspectRatio = 1f / aspectRatio;
+ }
+ mAspectRatio = aspectRatio;
+ updateTransform();
+ }
+
+ public void updateTransform(Matrix matrix) {
+ RectF previewRect = new RectF(0, 0, mWidth, mHeight);
+ matrix.mapRect(previewRect);
+
+ float previewWidth = previewRect.width();
+ float previewHeight = previewRect.height();
+ if (previewHeight == 0 || previewWidth == 0) {
+ Log.e(TAG, "Invalid preview size: " + previewWidth + " x " + previewHeight);
+ return;
+ }
+ mPreview.setTransform(matrix);
+
+ onPreviewSizeChanged(previewWidth, previewHeight);
+ }
+
+ public void setOnLayoutChangeListener(OnLayoutChangeListener listener) {
+ mOnLayoutChangeListener = listener;
+ }
+
+ public void setSurfaceTextureListener(TextureView.SurfaceTextureListener listener) {
+ mSurfaceTextureListener = listener;
+ }
+
+ /**
+ * Updates the transform matrix based current width and height of TextureView
+ * and preview stream aspect ratio.
+ */
+ private void updateTransform() {
+ if (mAspectRatio == UNSET || mAspectRatio < 0 || mWidth == 0 || mHeight == 0) {
+ return;
+ }
+
+ Matrix matrix = mPreview.getTransform(null);
+ float scaledTextureWidth, scaledTextureHeight;
+ if (mWidth > mHeight) {
+ scaledTextureWidth = Math.min(mWidth,
+ (int) (mHeight * mAspectRatio));
+ scaledTextureHeight = Math.min(mHeight,
+ (int) (mWidth / mAspectRatio));
+ } else {
+ scaledTextureWidth = Math.min(mWidth,
+ (int) (mHeight / mAspectRatio));
+ scaledTextureHeight = Math.min(mHeight,
+ (int) (mWidth * mAspectRatio));
+ }
+
+ float scaleX = scaledTextureWidth / mWidth;
+ float scaleY = scaledTextureHeight / mHeight;
+
+ boolean landscape = mWidth > mHeight;
+ if (landscape) {
+ matrix.setScale(scaleX, scaleY, 0f, (float) mHeight / 2);
+ } else {
+ matrix.setScale(scaleX, scaleY, (float) mWidth / 2, 0.0f);
+ }
+ mPreview.setTransform(matrix);
+ onPreviewSizeChanged(scaledTextureWidth, scaledTextureHeight);
+ }
+
+ private void onPreviewSizeChanged(float scaledTextureWidth, float scaledTextureHeight) {
+ // Notify listeners of preview size change
+ if (mPreviewSizeChangedListener == null) {
+ return;
+ }
+ mPreviewSizeChangedListener.onPreviewSizeChanged(scaledTextureWidth, scaledTextureHeight);
+ }
+
+ /**
+ * Sets a listener that will get notified when the preview size changed. This
+ * can be useful for UI elements or focus overlay to adjust themselves according
+ * to the preview size change.
+ *
+ * @param listener the listener that will get notified of preview size change
+ */
+ public void setPreviewSizeChangedListener(
+ PreviewStatusListener.PreviewSizeChangedListener listener) {
+ mPreviewSizeChangedListener = listener;
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ // Workaround for b/11168275, see b/10981460 for more details
+ if (mWidth != 0 && mHeight != 0) {
+ // Re-apply transform matrix for new surface texture
+ updateTransform();
+ }
+ if (mSurfaceTextureListener != null) {
+ mSurfaceTextureListener.onSurfaceTextureAvailable(surface, width, height);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ if (mSurfaceTextureListener != null) {
+ mSurfaceTextureListener.onSurfaceTextureSizeChanged(surface, width, height);
+ }
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ if (mSurfaceTextureListener != null) {
+ mSurfaceTextureListener.onSurfaceTextureDestroyed(surface);
+ }
+ return false;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ if (mSurfaceTextureListener != null) {
+ mSurfaceTextureListener.onSurfaceTextureUpdated(surface);
+ }
+
+ }
+}
diff --git a/src/com/android/camera/VideoController.java b/src/com/android/camera/VideoController.java
index 978b43862..5e17f4959 100644
--- a/src/com/android/camera/VideoController.java
+++ b/src/com/android/camera/VideoController.java
@@ -35,6 +35,7 @@ public interface VideoController extends OnShutterButtonListener {
public void stopPreview();
public void updateCameraOrientation();
+ public void updatePreviewAspectRatio(float aspectRatio);
// Callbacks for camera preview UI events.
public void onPreviewUIReady();
@@ -46,4 +47,5 @@ public interface VideoController extends OnShutterButtonListener {
* Starts the pre-capture animation.
*/
public void startPreCaptureAnimation();
+
}
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 6153ae9fc..566d53cd8 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -611,6 +611,11 @@ public class VideoModule extends CameraModule
}
@Override
+ public void updatePreviewAspectRatio(float aspectRatio) {
+ mAppController.updatePreviewAspectRatio(aspectRatio);
+ }
+
+ @Override
public int onZoomChanged(int index) {
// Not useful to change zoom value when the activity is paused.
if (mPaused) return index;
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 802f396cf..127f7a03d 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -27,7 +27,6 @@ import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -46,6 +45,7 @@ import java.util.List;
public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
private static final String TAG = "CAM_VideoUI";
+ private final static float UNSET = 0f;
private final PreviewOverlay mPreviewOverlay;
// module fields
private final CameraActivity mActivity;
@@ -68,15 +68,10 @@ public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
private List<Integer> mZoomRatios;
private final BottomBar mBottomBar;
- private final int mBottomBarMinHeight;
- private final int mBottomBarOptimalHeight;
private SurfaceView mSurfaceView = null;
- private int mPreviewWidth = 0;
- private int mPreviewHeight = 0;
private float mSurfaceTextureUncroppedWidth;
private float mSurfaceTextureUncroppedHeight;
- private float mAspectRatio = 16f / 9f;
private ButtonManager.ButtonCallback mFlashCallback;
private ButtonManager.ButtonCallback mCameraCallback;
@@ -101,25 +96,22 @@ public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
}
};
+ private float mAspectRatio = UNSET;
private final AnimationManager mAnimationManager;
@Override
public void onPreviewLayoutChanged(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- int width = right - left;
- int height = bottom - top;
- // Full-screen screennail
- int w = width;
- int h = height;
- if (CameraUtil.getDisplayRotation(mActivity) % 180 != 0) {
- w = height;
- h = width;
- }
- if (mPreviewWidth != width || mPreviewHeight != height) {
- mPreviewWidth = width;
- mPreviewHeight = height;
- onScreenSizeChanged(width, height, w, h);
- }
+ }
+
+ @Override
+ public boolean shouldAutoAdjustTransformMatrixOnLayout() {
+ return true;
+ }
+
+ @Override
+ public boolean shouldAutoAdjustBottomBar() {
+ return true;
}
private final GestureDetector.OnGestureListener mPreviewGestureListener
@@ -141,23 +133,13 @@ public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
moduleRoot, true);
mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
-
mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
- mPreviewWidth = mTextureView.getWidth();
- mPreviewHeight = mTextureView.getHeight();
mBottomBar = (BottomBar) mRootView.findViewById(R.id.bottom_bar);
mBottomBar.setButtonLayout(R.layout.video_bottombar_buttons);
- mBottomBarMinHeight = activity.getResources()
- .getDimensionPixelSize(R.dimen.bottom_bar_height_min);
- mBottomBarOptimalHeight = activity.getResources()
- .getDimensionPixelSize(R.dimen.bottom_bar_height_optimal);
mBottomBar.setBackgroundColor(activity.getResources().getColor(R.color.video_mode_color));
mSurfaceTexture = mTextureView.getSurfaceTexture();
- if (mSurfaceTexture != null) {
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
- }
initializeMiscControls();
initializeControlByIntent();
@@ -230,15 +212,6 @@ public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
setAspectRatio(aspectRatio);
}
- public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) {
- setTransformMatrix(width, height);
- }
-
- private void setTransformMatrix(int width, int height) {
- mActivity.getCameraAppUI().adjustPreviewAndBottomBarSize(width, height, mBottomBar,
- mAspectRatio, mBottomBarMinHeight, mBottomBarOptimalHeight);
- }
-
/**
* Starts a flash animation
*/
@@ -296,13 +269,11 @@ public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
public void hideSurfaceView() {
mSurfaceView.setVisibility(View.GONE);
mTextureView.setVisibility(View.VISIBLE);
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
}
public void showSurfaceView() {
mSurfaceView.setVisibility(View.VISIBLE);
mTextureView.setVisibility(View.GONE);
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
}
public void onCameraOpened(ButtonManager.ButtonCallback flashCallback,
@@ -337,7 +308,7 @@ public class VideoUI implements PreviewStatusListener, SurfaceHolder.Callback {
float aspectRatio = ratio > 1 ? ratio : 1 / ratio;
if (aspectRatio != mAspectRatio) {
mAspectRatio = aspectRatio;
- setTransformMatrix(mPreviewWidth, mPreviewHeight);
+ mController.updatePreviewAspectRatio(mAspectRatio);
}
}
diff --git a/src/com/android/camera/app/AppController.java b/src/com/android/camera/app/AppController.java
index b9976f4b6..42046f033 100644
--- a/src/com/android/camera/app/AppController.java
+++ b/src/com/android/camera/app/AppController.java
@@ -19,6 +19,7 @@ package com.android.camera.app;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.net.Uri;
import android.widget.FrameLayout;
@@ -101,6 +102,23 @@ public interface AppController {
public void onPreviewStarted();
/**
+ * Gets called from module when preview aspect ratio has changed.
+ *
+ * @param aspectRatio aspect ratio of preview stream
+ */
+ public void updatePreviewAspectRatio(float aspectRatio);
+
+ /**
+ * Gets called from module when the module needs to change the transform matrix
+ * of the preview TextureView. It is encouraged to use
+ * {@link #updatePreviewAspectRatio(float)} over this function, unless the module
+ * needs to rotate the surface texture using transform matrix.
+ *
+ * @param matrix transform matrix to be set on preview TextureView
+ */
+ public void updatePreviewTransform(Matrix matrix);
+
+ /**
* Sets the preview status listener, which will get notified when TextureView
* surface has changed
*
diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java
index 1109ee6af..169a31cf3 100644
--- a/src/com/android/camera/app/CameraAppUI.java
+++ b/src/com/android/camera/app/CameraAppUI.java
@@ -32,6 +32,7 @@ import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import com.android.camera.AnimationManager;
+import com.android.camera.TextureViewHelper;
import com.android.camera.filmstrip.FilmstripContentPanel;
import com.android.camera.ui.BottomBar;
import com.android.camera.ui.CaptureAnimationOverlay;
@@ -206,9 +207,10 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
private final ModeListView mModeListView;
private final FilmstripLayout mFilmstripLayout;
private TextureView mTextureView;
- private View mFlashOverlay;
private FrameLayout mModuleUI;
+ private BottomBar mBottomBar;
+ private TextureViewHelper mTextureViewHelper;
private final GestureDetector mGestureDetector;
private int mSwipeState = IDLE;
private PreviewOverlay mPreviewOverlay;
@@ -230,114 +232,18 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
}
};
- // TODO this isn't used by all modules universally, should be part of a util class or something
- /**
- * Resizes the preview texture and given bottom bar for 100% preview size
- */
- public void adjustPreviewAndBottomBarSize(int width, int height,
- BottomBar bottomBar, float aspectRatio,
- int bottomBarMinHeight, int bottomBarOptimalHeight) {
- Matrix matrix = mTextureView.getTransform(null);
-
- float scaleX = 1f, scaleY = 1f;
- float scaledTextureWidth, scaledTextureHeight;
- if (width > height) {
- scaledTextureWidth = Math.min(width,
- (int) (height * aspectRatio));
- scaledTextureHeight = Math.min(height,
- (int) (width / aspectRatio));
- } else {
- scaledTextureWidth = Math.min(width,
- (int) (height / aspectRatio));
- scaledTextureHeight = Math.min(height,
- (int) (width * aspectRatio));
- }
-
- scaleX = scaledTextureWidth / width;
- scaleY = scaledTextureHeight / height;
-
- // TODO: Need a better way to find out whether currently in landscape
- boolean landscape = width > height;
- if (landscape) {
- matrix.setScale(scaleX, scaleY, 0f, (float) height / 2);
- } else {
- matrix.setScale(scaleX, scaleY, (float) width / 2, 0.0f);
- }
- setPreviewTransformMatrix(matrix);
- adjustBottomBar(width, height, bottomBar, bottomBarOptimalHeight, scaledTextureWidth,
- scaledTextureHeight, landscape);
- }
-
- private void adjustBottomBar(int width, int height, BottomBar bottomBar,
- int bottomBarOptimalHeight, float scaledTextureWidth,
- float scaledTextureHeight, boolean landscape) {
- float previewAspectRatio =
- scaledTextureWidth / scaledTextureHeight;
- if (previewAspectRatio < 1.0) {
- previewAspectRatio = 1.0f/previewAspectRatio;
- }
- float screenAspectRatio = (float)width / (float)height;
- if (screenAspectRatio < 1.0) {
- screenAspectRatio = 1.0f/screenAspectRatio;
- }
-
- if(bottomBar != null) {
- LayoutParams lp = (LayoutParams) bottomBar.getLayoutParams();
- // TODO accoount for cases where resizes bar height would be < bottomBarMinHeight
- if (previewAspectRatio >= screenAspectRatio) {
- bottomBar.setAlpha(0.5f);
- if (landscape) {
- lp.width = bottomBarOptimalHeight;
- lp.height = LayoutParams.MATCH_PARENT;
- } else {
- lp.height = bottomBarOptimalHeight;
- lp.width = LayoutParams.MATCH_PARENT;
- }
- } else {
- bottomBar.setAlpha(1.0f);
- if (landscape) {
- lp.width = (int)(width - scaledTextureWidth);
- lp.height = LayoutParams.MATCH_PARENT;
- } else {
- lp.height = (int)(height - scaledTextureHeight);
- lp.width = LayoutParams.MATCH_PARENT;
- }
- }
- bottomBar.setLayoutParams(lp);
- }
+ public void updatePreviewAspectRatio(float aspectRatio) {
+ mTextureViewHelper.updateAspectRatio(aspectRatio);
}
/**
* This is to support modules that calculate their own transform matrix because
* they need to use a transform matrix to rotate the preview.
*
- * @param width width of the TextureView where preview is hosted
- * @param height height of the TextureView where preview is hosted
* @param matrix transform matrix to be set on the TextureView
*/
- public void updatePreviewTransform(int width, int height, Matrix matrix) {
- if (width == 0 || height == 0) {
- Log.e(TAG, "Invalid screen size: " + width + " x " + height);
- return;
- }
- int bottomBarMinHeight = mCameraRootView.getResources()
- .getDimensionPixelSize(R.dimen.bottom_bar_height_min);
- int bottomBarOptimalHeight = mCameraRootView.getResources()
- .getDimensionPixelSize(R.dimen.bottom_bar_height_optimal);
- RectF previewRect = new RectF(0, 0, width, height);
- matrix.mapRect(previewRect);
-
- float previewWidth = previewRect.width();
- float previewHeight = previewRect.height();
- if (previewHeight == 0 || previewWidth == 0) {
- Log.e(TAG, "Invalid preview size: " + previewWidth + " x " + previewHeight);
- return;
- }
-
- BottomBar bottomBar = (BottomBar) mCameraRootView.findViewById(R.id.bottom_bar);
- setPreviewTransformMatrix(matrix);
- adjustBottomBar(width, height, bottomBar, bottomBarOptimalHeight, previewWidth,
- previewHeight, width > height);
+ public void updatePreviewTransform(Matrix matrix) {
+ mTextureViewHelper.updateTransform(matrix);
}
public interface AnimationFinishedListener {
@@ -561,6 +467,12 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
if (gestureListener != null) {
mPreviewOverlay.setGestureListener(gestureListener);
}
+ mTextureViewHelper.setAutoAdjustTransform(
+ mPreviewStatusListener.shouldAutoAdjustTransformMatrixOnLayout());
+ if (mPreviewStatusListener.shouldAutoAdjustBottomBar()) {
+ mBottomBar = (BottomBar) mCameraRootView.findViewById(R.id.bottom_bar);
+ mTextureViewHelper.setPreviewSizeChangedListener(mBottomBar);
+ }
}
}
@@ -579,8 +491,10 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
mModuleUI = (FrameLayout) mCameraRootView.findViewById(R.id.module_layout);
mTextureView = (TextureView) mCameraRootView.findViewById(R.id.preview_content);
- mTextureView.addOnLayoutChangeListener(mPreviewLayoutChangeListener);
- mTextureView.setSurfaceTextureListener(this);
+ mTextureViewHelper = new TextureViewHelper(mTextureView);
+ mTextureViewHelper.setSurfaceTextureListener(this);
+ mTextureViewHelper.setOnLayoutChangeListener(mPreviewLayoutChangeListener);
+
mPreviewOverlay = (PreviewOverlay) mCameraRootView.findViewById(R.id.preview_overlay);
mPreviewOverlay.setOnTouchListener(new MyTouchListener());
mCaptureOverlay = (CaptureAnimationOverlay)
@@ -592,10 +506,8 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
public void clearCameraUI() {
mCameraRootView.removeAllViews();
mModuleUI = null;
- mTextureView.removeOnLayoutChangeListener(mPreviewLayoutChangeListener);
mTextureView = null;
mPreviewOverlay = null;
- mFlashOverlay = null;
}
/**
@@ -616,6 +528,9 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
if (mModuleUI != null) {
mModuleUI.removeAllViews();
}
+ // TODO: Remove this when bottom bar is at the app level
+ mBottomBar = null;
+ mTextureViewHelper.setPreviewSizeChangedListener(null);
mPreviewStatusListener = null;
mPreviewOverlay.reset();
@@ -663,18 +578,6 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
}
}
- /**
- * Sets the transform matrix on the preview TextureView
- */
- public void setPreviewTransformMatrix(Matrix transformMatrix) {
- if (mTextureView == null) {
- throw new UnsupportedOperationException("Cannot set transform matrix on a null" +
- " TextureView");
- }
- mTextureView.setTransform(transformMatrix);
- }
-
-
/********************** Capture animation **********************/
/* TODO: This session is subject to UX changes. In addition to the generic
flash animation and post capture animation, consider designating a parameter
diff --git a/src/com/android/camera/ui/BottomBar.java b/src/com/android/camera/ui/BottomBar.java
index 84dbb8727..9d1307bc8 100644
--- a/src/com/android/camera/ui/BottomBar.java
+++ b/src/com/android/camera/ui/BottomBar.java
@@ -19,6 +19,7 @@ package com.android.camera.ui;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -27,6 +28,8 @@ import android.widget.GridLayout;
import android.widget.LinearLayout;
import android.view.MotionEvent;
+import com.android.camera2.R;
+
/**
* BottomBar swaps its width and height on rotation. In addition, it also changes
* gravity and layout orientation based on the new orientation. Specifically, in
@@ -37,9 +40,18 @@ import android.view.MotionEvent;
* In addition to adjusting itself, this class also makes sure its children are
* always spaced evenly in the new orientation.
*/
-public class BottomBar extends FrameLayout {
+public class BottomBar extends FrameLayout
+ implements PreviewStatusListener.PreviewSizeChangedListener {
+ private static final String TAG = "BottomBar";
private final int mPaddingStart;
private final int mPaddingEnd;
+ private int mWidth;
+ private int mHeight;
+ private float mOffsetShorterEdge;
+ private float mOffsetLongerEdge;
+
+ private final int mOptimalHeight;
+ private boolean mOverLayBottomBar;
public BottomBar(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -52,6 +64,7 @@ public class BottomBar extends FrameLayout {
mPaddingStart = getPaddingLeft();
mPaddingEnd = getPaddingRight();
}
+ mOptimalHeight = getResources().getDimensionPixelSize(R.dimen.bottom_bar_height_optimal);
}
/**
@@ -64,34 +77,88 @@ public class BottomBar extends FrameLayout {
inflater.inflate(buttonLayoutId, this, true);
}
- /**
- * Adjust layout orientation, width, height and gravity based on new orientation.
- */
- private void adjustSelf(Configuration configuration) {
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- int shortEdge;
- if (lp.width != FrameLayout.LayoutParams.MATCH_PARENT) {
- shortEdge = lp.width;
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ mWidth = MeasureSpec.getSize(widthMeasureSpec);
+ mHeight = MeasureSpec.getSize(heightMeasureSpec);
+ if (mWidth == 0 || mHeight == 0) {
+ return;
+ }
+
+ if (mOffsetShorterEdge != 0 && mOffsetLongerEdge != 0) {
+ float previewAspectRatio =
+ mOffsetLongerEdge / mOffsetShorterEdge;
+ if (previewAspectRatio < 1.0) {
+ previewAspectRatio = 1.0f/previewAspectRatio;
+ }
+ float screenAspectRatio = (float) mWidth / (float) mHeight;
+ if (screenAspectRatio < 1.0) {
+ screenAspectRatio = 1.0f/screenAspectRatio;
+ }
+ if (previewAspectRatio >= screenAspectRatio) {
+ mOverLayBottomBar = true;
+ setAlpha(0.5f);
+ } else {
+ mOverLayBottomBar = false;
+ setAlpha(1.0f);
+ }
+ }
+
+ // Calculates the width and height needed for the bar.
+ int barWidth, barHeight;
+ if (mWidth > mHeight) {
+ ((LayoutParams) getLayoutParams()).gravity = Gravity.RIGHT;
+ if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) {
+ barWidth = mOptimalHeight;
+ barHeight = mHeight;
+ } else {
+ barWidth = (int) (mWidth - mOffsetLongerEdge);
+ barHeight = mHeight;
+ }
} else {
- shortEdge = lp.height;
+ ((LayoutParams) getLayoutParams()).gravity = Gravity.BOTTOM;
+ if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) {
+ barWidth = mWidth;
+ barHeight = mOptimalHeight;
+ } else {
+ barWidth = mWidth;
+ barHeight = (int) (mHeight - mOffsetLongerEdge);
+ }
}
- if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
- lp.width = FrameLayout.LayoutParams.MATCH_PARENT;
- lp.height = shortEdge;
- lp.gravity = Gravity.BOTTOM;
- setLayoutParams(lp);
+ super.onMeasure(MeasureSpec.makeMeasureSpec(barWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(barHeight, MeasureSpec.EXACTLY));
+ }
+
+ private void adjustBottomBar(float scaledTextureWidth,
+ float scaledTextureHeight) {
+ setOffset(scaledTextureWidth, scaledTextureHeight);
+ }
+
+ @Override
+ public void onPreviewSizeChanged(float scaledTextureWidth,
+ float scaledTextureHeight) {
+ adjustBottomBar(scaledTextureWidth, scaledTextureHeight);
+ }
+
+ private void setOffset(float scaledTextureWidth, float scaledTextureHeight) {
+ float offsetLongerEdge, offsetShorterEdge;
+ if (scaledTextureHeight > scaledTextureWidth) {
+ offsetLongerEdge = scaledTextureHeight;
+ offsetShorterEdge = scaledTextureWidth;
} else {
- lp.height = FrameLayout.LayoutParams.MATCH_PARENT;
- lp.width = shortEdge;
- lp.gravity = Gravity.RIGHT;
- setLayoutParams(lp);
+ offsetLongerEdge = scaledTextureWidth;
+ offsetShorterEdge = scaledTextureHeight;
+ }
+ if (mOffsetLongerEdge != offsetLongerEdge || mOffsetShorterEdge != offsetShorterEdge) {
+ mOffsetLongerEdge = offsetLongerEdge;
+ mOffsetShorterEdge = offsetShorterEdge;
+ requestLayout();
}
}
@Override
protected void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
- adjustSelf(config);
}
/**
diff --git a/src/com/android/camera/ui/PreviewStatusListener.java b/src/com/android/camera/ui/PreviewStatusListener.java
index d9d23ed25..54615abd0 100644
--- a/src/com/android/camera/ui/PreviewStatusListener.java
+++ b/src/com/android/camera/ui/PreviewStatusListener.java
@@ -39,4 +39,30 @@ public interface PreviewStatusListener extends TextureView.SurfaceTextureListene
*/
public void onPreviewLayoutChanged(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom);
+
+ /**
+ * This listener gets notified when the actual preview frame changes size due
+ * to a transform matrix being applied to the TextureView
+ */
+ public interface PreviewSizeChangedListener {
+ public void onPreviewSizeChanged(float previewWidth, float previewHeight);
+ }
+
+ /**
+ * The preview status listener needs to know for the specific module whether
+ * preview TextureView should automatically adjust its transform matrix based
+ * on the current aspect ratio, width and height of the TextureView.
+ *
+ * @return whether transform matrix should be automatically adjusted
+ */
+ public boolean shouldAutoAdjustTransformMatrixOnLayout();
+
+ /**
+ * The preview status listener needs to know for the specific module whether
+ * bottom bar should be automatically adjusted when preview has changed size
+ * or orientation.
+ *
+ * @return whether bottom bar should be automatically adjusted
+ */
+ public boolean shouldAutoAdjustBottomBar();
}