From 6a0de79a7066d4ae5cc4677f88989abd15e892ff Mon Sep 17 00:00:00 2001 From: Doris Liu Date: Tue, 26 Feb 2013 10:54:25 -0800 Subject: Flatten view hierarchy and rotate views TODO: SRI pano and Lightcycle can use a bit more flattening. I will get to them next. (Maybe in a different CL.) TODO: Need to cancel capture animation in onConfigurationChanged() Change-Id: I00fd3e098117d9fb74fde2c128407ab6275bcedf --- src/com/android/camera/CameraActivity.java | 40 +++---- src/com/android/camera/CameraModule.java | 2 + src/com/android/camera/PanoramaModule.java | 11 +- src/com/android/camera/PhotoModule.java | 156 +++++++----------------- src/com/android/camera/PreviewFrameLayout.java | 9 -- src/com/android/camera/ShutterButton.java | 9 ++ src/com/android/camera/VideoModule.java | 92 +++++--------- src/com/android/camera/ui/CameraSwitcher.java | 13 ++ src/com/android/camera/ui/RotatableLayout.java | 158 +++++++++++++++++++++++++ 9 files changed, 285 insertions(+), 205 deletions(-) create mode 100644 src/com/android/camera/ui/RotatableLayout.java diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index b5ff0114c..eed347079 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -41,6 +41,7 @@ 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; @@ -57,8 +58,10 @@ public class CameraActivity extends ActivityBase private FrameLayout mFrame; private ShutterButton mShutter; private CameraSwitcher mSwitcher; - private View mShutterSwitcher; + private View mCameraControls; private View mControlsBackground; + private View mPieMenuButton; + private View mSwitcherControl; private Drawable[] mDrawables; private int mCurrentModuleIndex; private MotionEvent mDown; @@ -94,7 +97,7 @@ public class CameraActivity extends ActivityBase public void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.camera_main); - mFrame = (FrameLayout) findViewById(R.id.main_content); + mFrame = (FrameLayout) findViewById(R.id.camera_app_root); mDrawables = new Drawable[DRAW_IDS.length]; for (int i = 0; i < DRAW_IDS.length; i++) { mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]); @@ -115,10 +118,12 @@ public class CameraActivity extends ActivityBase } public void init() { - mControlsBackground = findViewById(R.id.controls); - mShutterSwitcher = findViewById(R.id.camera_shutter_switcher); + mControlsBackground = findViewById(R.id.blocker); + mCameraControls = findViewById(R.id.camera_controls); mShutter = (ShutterButton) findViewById(R.id.shutter_button); mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher); + mPieMenuButton = findViewById(R.id.menu_button); + mSwitcherControl = findViewById(R.id.switcher_control); int totaldrawid = (LightCycleHelper.hasLightCycleCapture(this) ? DRAW_IDS.length : DRAW_IDS.length - 1); if (!ApiHelper.HAS_OLD_PANORAMA) totaldrawid--; @@ -217,6 +222,11 @@ public class CameraActivity extends ActivityBase mCurrentModule = LightCycleHelper.createPanoramaModule(); break; } + if (mCurrentModule.needsPieMenu()) { + mPieMenuButton.setVisibility(View.VISIBLE); + } else { + mPieMenuButton.setVisibility(View.INVISIBLE); + } openModule(mCurrentModule, canReuse); mCurrentModule.onOrientationChanged(mLastRawOrientation); if (mMediaSaveService != null) { @@ -268,13 +278,13 @@ public class CameraActivity extends ActivityBase } public void hideUI() { - mControlsBackground.setVisibility(View.INVISIBLE); + mCameraControls.setVisibility(View.INVISIBLE); hideSwitcher(); mShutter.setVisibility(View.GONE); } public void showUI() { - mControlsBackground.setVisibility(View.VISIBLE); + mCameraControls.setVisibility(View.VISIBLE); showSwitcher(); mShutter.setVisibility(View.VISIBLE); // Force a layout change to show shutter button @@ -310,20 +320,10 @@ public class CameraActivity extends ActivityBase } appRoot.setLayoutParams(lp); - // remove old switcher, shutter and shutter icon - View cameraControlsView = findViewById(R.id.camera_shutter_switcher); - appRoot.removeView(cameraControlsView); - - // create new layout with the current orientation - LayoutInflater inflater = getLayoutInflater(); - inflater.inflate(R.layout.camera_shutter_switcher, appRoot); - init(); + // Reset the background after rotation + mControlsBackground.setBackgroundResource(0); // remove the current background + mControlsBackground.setBackgroundResource(R.drawable.switcher_bg); - if (mShowCameraAppView) { - showUI(); - } else { - hideUI(); - } mCurrentModule.onConfigurationChanged(config); } @@ -466,7 +466,7 @@ public class CameraActivity extends ActivityBase if ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) { return mSwitcher.onTouch(null, m); } else { - return mShutterSwitcher.dispatchTouchEvent(m) + return mSwitcherControl.dispatchTouchEvent(m) || mCurrentModule.dispatchTouchEvent(m); } } diff --git a/src/com/android/camera/CameraModule.java b/src/com/android/camera/CameraModule.java index 37eabd0a3..aa057b916 100644 --- a/src/com/android/camera/CameraModule.java +++ b/src/com/android/camera/CameraModule.java @@ -68,6 +68,8 @@ public interface CameraModule { public boolean needsSwitcher(); + public boolean needsPieMenu(); + public void onOrientationChanged(int orientation); public void onShowSwitcherPopup(); diff --git a/src/com/android/camera/PanoramaModule.java b/src/com/android/camera/PanoramaModule.java index 4edc68657..d12c8286e 100644 --- a/src/com/android/camera/PanoramaModule.java +++ b/src/com/android/camera/PanoramaModule.java @@ -714,13 +714,13 @@ public class PanoramaModule implements CameraModule, } private void createContentView() { - mActivity.getLayoutInflater().inflate(R.layout.panorama_module, (ViewGroup) mRootView); + mActivity.getLayoutInflater().inflate(R.layout.panorama_module, (ViewGroup) mRootView, true); Resources appRes = mActivity.getResources(); - mCaptureLayout = (LinearLayout) mRootView.findViewById(R.id.camera_app_root); + mCaptureLayout = (LinearLayout) mRootView.findViewById(R.id.camera_app); mIndicatorColor = appRes.getColor(R.color.pano_progress_indication); mReviewBackground = appRes.getColor(R.color.review_background); mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast); - mPanoLayout = (ViewGroup) mRootView.findViewById(R.id.pano_layout); + mPanoLayout = (ViewGroup) mRootView.findViewById(R.id.camera_app_root); mRotateDialog = new RotateDialogController(mActivity, R.layout.rotate_dialog); setViews(appRes); } @@ -1307,6 +1307,11 @@ public class PanoramaModule implements CameraModule, return true; } + @Override + public boolean needsPieMenu() { + return false; + } + @Override public void onShowSwitcherPopup() { } diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index e244d6b88..664246a8a 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -52,6 +52,7 @@ import android.view.MotionEvent; import android.view.OrientationEventListener; import android.view.SurfaceHolder; import android.view.View; +import android.view.ViewStub; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; @@ -66,11 +67,8 @@ import com.android.camera.ui.CountDownView; import com.android.camera.ui.FaceView; import com.android.camera.ui.PieRenderer; import com.android.camera.ui.PopupManager; -import com.android.camera.ui.PreviewSurfaceView; import com.android.camera.ui.RenderOverlay; -import com.android.camera.ui.Rotatable; import com.android.camera.ui.RotateTextToast; -import com.android.camera.ui.TwoStateImageView; import com.android.camera.ui.ZoomRenderer; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; @@ -92,7 +90,6 @@ public class PhotoModule FocusOverlayManager.Listener, CameraPreference.OnPreferenceChangedListener, LocationManager.Listener, - PreviewFrameLayout.OnSizeChangedListener, ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, PieRenderer.PieListener, @@ -172,18 +169,15 @@ public class PhotoModule private ShutterButton mShutterButton; private boolean mFaceDetectionStarted = false; - private PreviewFrameLayout mPreviewFrameLayout; private Object mSurfaceTexture; private CountDownView mCountDownView; - // for API level 10 - private PreviewSurfaceView mPreviewSurfaceView; private volatile SurfaceHolder mCameraSurfaceHolder; private FaceView mFaceView; private RenderOverlay mRenderOverlay; - private Rotatable mReviewCancelButton; - private Rotatable mReviewDoneButton; + private View mReviewCancelButton; + private View mReviewDoneButton; private View mReviewRetakeButton; // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. @@ -288,7 +282,6 @@ public class PhotoModule private PhotoController mPhotoControl; private ZoomRenderer mZoomRenderer; - private String mSceneMode; private Toast mNotSelectableToast; @@ -466,7 +459,16 @@ public class PhotoModule mCameraStartUpThread = new CameraStartUpThread(); mCameraStartUpThread.start(); - mActivity.getLayoutInflater().inflate(R.layout.photo_module, (ViewGroup) mRootView); + mActivity.getLayoutInflater().inflate(R.layout.photo_module, + (ViewGroup) mRootView, true); + if (ApiHelper.HAS_FACE_DETECTION) { + ViewStub faceViewStub = (ViewStub) mRootView + .findViewById(R.id.face_view_stub); + if (faceViewStub != null) { + faceViewStub.inflate(); + mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); + } + } // Surface texture is from camera screen nail and startPreview needs it. // This must be done before startPreview. @@ -487,7 +489,6 @@ public class PhotoModule initializeControlByIntent(); mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); - initializeMiscControls(); mLocationManager = new LocationManager(mActivity, this); initOnScreenIndicator(); mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture)); @@ -557,10 +558,10 @@ public class PhotoModule if (isImageCaptureIntent()) { if (mReviewCancelButton != null) { - mGestures.addTouchReceiver((View) mReviewCancelButton); + mGestures.addTouchReceiver(mReviewCancelButton); } if (mReviewDoneButton != null) { - mGestures.addTouchReceiver((View) mReviewDoneButton); + mGestures.addTouchReceiver(mReviewDoneButton); } } } @@ -585,9 +586,17 @@ public class PhotoModule initializePhotoControl(); // These depend on camera parameters. - setPreviewFrameLayoutAspectRatio(); - mFocusManager.setPreviewSize(mPreviewFrameLayout.getWidth(), - mPreviewFrameLayout.getHeight()); + int width = mActivity.getWindowManager().getDefaultDisplay().getWidth(); + int height = mActivity.getWindowManager().getDefaultDisplay().getHeight(); + mFocusManager.setPreviewSize(width, height); + // Full-screen screennail + if (Util.getDisplayRotation(mActivity) % 180 == 0) { + ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(width, height); + } else { + ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(height, width); + } + // Set touch focus listener. + mActivity.setSingleTapUpListener(mRootView); loadCameraPreferences(); initializeZoom(); updateOnScreenIndicators(); @@ -795,7 +804,7 @@ public class PhotoModule } private void initOnScreenIndicator() { - mOnScreenIndicators = mRootView.findViewById(R.id.on_screen_indicators); + mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators); mExposureIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_exposure_indicator); mFlashIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_flash_indicator); mSceneIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_scenemode_indicator); @@ -1217,11 +1226,6 @@ public class PhotoModule } return; } - if (full) { - mPreviewSurfaceView.expand(); - } else { - mPreviewSurfaceView.shrink(); - } } @Override @@ -1623,8 +1627,8 @@ public class PhotoModule } private void initializeControlByIntent() { - mBlocker = mRootView.findViewById(R.id.blocker); - mMenu = mRootView.findViewById(R.id.menu); + mBlocker = mActivity.findViewById(R.id.blocker); + mMenu = mActivity.findViewById(R.id.menu); mMenu.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -1637,23 +1641,22 @@ public class PhotoModule } }); if (mIsImageCaptureIntent) { - mActivity.hideSwitcher(); - // Cannot use RotateImageView for "done" and "cancel" button because - // the tablet layout uses RotateLayout, which cannot be cast to - // RotateImageView. - mReviewDoneButton = (Rotatable) mRootView.findViewById(R.id.btn_done); - mReviewCancelButton = (Rotatable) mRootView.findViewById(R.id.btn_cancel); - mReviewRetakeButton = mRootView.findViewById(R.id.btn_retake); - ((View) mReviewCancelButton).setVisibility(View.VISIBLE); - - ((View) mReviewDoneButton).setOnClickListener(new OnClickListener() { + ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls); + mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls); + + mReviewDoneButton = mActivity.findViewById(R.id.btn_done); + mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); + mReviewRetakeButton = mActivity.findViewById(R.id.btn_retake); + mReviewCancelButton.setVisibility(View.VISIBLE); + + mReviewDoneButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewDoneClicked(v); } }); - ((View) mReviewCancelButton).setOnClickListener(new OnClickListener() { + mReviewCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewCancelClicked(v); @@ -1667,13 +1670,6 @@ public class PhotoModule } }); - // Not grayed out upon disabled, to make the follow-up fade-out - // effect look smooth. Note that the review done button in tablet - // layout is not a TwoStateImageView. - if (mReviewDoneButton instanceof TwoStateImageView) { - ((TwoStateImageView) mReviewDoneButton).enableFilter(false); - } - setupCaptureParams(); } } @@ -1700,62 +1696,10 @@ public class PhotoModule } } - private void initializeMiscControls() { - // startPreview needs this. - mPreviewFrameLayout = (PreviewFrameLayout) mRootView.findViewById(R.id.frame); - // Set touch focus listener. - mActivity.setSingleTapUpListener(mPreviewFrameLayout); - - mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); - mPreviewFrameLayout.setOnSizeChangedListener(this); - mPreviewFrameLayout.setOnLayoutChangeListener(mActivity); - if (!ApiHelper.HAS_SURFACE_TEXTURE) { - mPreviewSurfaceView = - (PreviewSurfaceView) mRootView.findViewById(R.id.preview_surface_view); - mPreviewSurfaceView.setVisibility(View.VISIBLE); - mPreviewSurfaceView.getHolder().addCallback(this); - } - } - @Override public void onConfigurationChanged(Configuration newConfig) { Log.v(TAG, "onConfigurationChanged"); setDisplayOrientation(); - - // Only the views in photo_module_content need to be removed and recreated - // i.e. CountDownView won't be recreated - ViewGroup viewGroup = (ViewGroup) mRootView.findViewById(R.id.camera_app); - viewGroup.removeAllViews(); - LayoutInflater inflater = mActivity.getLayoutInflater(); - inflater.inflate(R.layout.photo_module_content, (ViewGroup) viewGroup); - - // from onCreate() - initializeControlByIntent(); - - initializeFocusManager(); - initializeMiscControls(); - loadCameraPreferences(); - - // from initializeFirstTime() - mShutterButton = mActivity.getShutterButton(); - mShutterButton.setOnShutterButtonListener(this); - initializeZoom(); - initOnScreenIndicator(); - updateOnScreenIndicators(); - if (mFaceView != null) { - mFaceView.clear(); - mFaceView.setVisibility(View.VISIBLE); - mFaceView.setDisplayOrientation(mDisplayOrientation); - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - mFaceView.setMirror(info.facing == CameraInfo.CAMERA_FACING_FRONT); - mFaceView.resume(); - mFocusManager.setFaceView(mFaceView); - } - initializeRenderOverlay(); - onFullScreenChanged(mActivity.isInCameraApp()); - if (mJpegImageData != null) { // Jpeg data found, picture has been taken. - showPostCaptureAlert(); - } } @Override @@ -2258,7 +2202,7 @@ public class PhotoModule if (mIsImageCaptureIntent) { mOnScreenIndicators.setVisibility(View.GONE); mMenu.setVisibility(View.GONE); - Util.fadeIn((View) mReviewDoneButton); + Util.fadeIn(mReviewDoneButton); mShutterButton.setVisibility(View.INVISIBLE); Util.fadeIn(mReviewRetakeButton); } @@ -2268,7 +2212,7 @@ public class PhotoModule if (mIsImageCaptureIntent) { mOnScreenIndicators.setVisibility(View.VISIBLE); mMenu.setVisibility(View.VISIBLE); - Util.fadeOut((View) mReviewDoneButton); + Util.fadeOut(mReviewDoneButton); mShutterButton.setVisibility(View.VISIBLE); Util.fadeOut(mReviewRetakeButton); } @@ -2284,7 +2228,6 @@ public class PhotoModule mLocationManager.recordLocation(recordLocation); setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE); - setPreviewFrameLayoutAspectRatio(); updateOnScreenIndicators(); } @@ -2431,12 +2374,6 @@ public class PhotoModule Util.FOCUS_MODE_CONTINUOUS_PICTURE); } - // PreviewFrameLayout size has changed. - @Override - public void onSizeChanged(int width, int height) { - if (mFocusManager != null) mFocusManager.setPreviewSize(width, height); - } - @Override public void onCountDownFinished() { mSnapshotOnIdle = false; @@ -2444,17 +2381,16 @@ public class PhotoModule mFocusManager.onShutterUp(); } - void setPreviewFrameLayoutAspectRatio() { - // Set the preview frame aspect ratio according to the picture size. - Size size = mParameters.getPictureSize(); - mPreviewFrameLayout.setAspectRatio((double) size.width / size.height); - } - @Override public boolean needsSwitcher() { return !mIsImageCaptureIntent; } + @Override + public boolean needsPieMenu() { + return true; + } + public void showPopup(AbstractSettingPopup popup) { mActivity.hideUI(); mBlocker.setVisibility(View.INVISIBLE); diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java index 87e3c8dfc..03ef91c60 100644 --- a/src/com/android/camera/PreviewFrameLayout.java +++ b/src/com/android/camera/PreviewFrameLayout.java @@ -54,15 +54,6 @@ public class PreviewFrameLayout extends RelativeLayout implements LayoutChangeNo @Override protected void onFinishInflate() { mBorder = findViewById(R.id.preview_border); - if (ApiHelper.HAS_FACE_DETECTION) { - ViewStub faceViewStub = (ViewStub) findViewById(R.id.face_view_stub); - /* preview_frame_video.xml does not have face view stub, so we need to - * check that. - */ - if (faceViewStub != null) { - faceViewStub.inflate(); - } - } } public void setAspectRatio(double ratio) { diff --git a/src/com/android/camera/ShutterButton.java b/src/com/android/camera/ShutterButton.java index a1bbb1a0d..41775a186 100755 --- a/src/com/android/camera/ShutterButton.java +++ b/src/com/android/camera/ShutterButton.java @@ -17,11 +17,14 @@ 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 @@ -127,4 +130,10 @@ public class ShutterButton extends ImageView { } return result; } + + @Override + public void onConfigurationChanged(Configuration config) { + super.onConfigurationChanged(config); + RotatableLayout.rotate(this, config.orientation == Configuration.ORIENTATION_PORTRAIT); + } } diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 245ef5990..7bda657a2 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -73,7 +73,6 @@ import com.android.camera.ui.Rotatable; import com.android.camera.ui.RotateImageView; import com.android.camera.ui.RotateLayout; import com.android.camera.ui.RotateTextToast; -import com.android.camera.ui.TwoStateImageView; import com.android.camera.ui.ZoomRenderer; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; @@ -142,14 +141,13 @@ public class VideoModule implements CameraModule, private SurfaceHolder.Callback mSurfaceViewCallback; private PreviewSurfaceView mPreviewSurfaceView; private CameraScreenNail.OnFrameDrawnListener mFrameDrawnListener; - private View mReviewControl; // An review image having same size as preview. It is displayed when // recording is stopped in capture intent. private ImageView mReviewImage; - private Rotatable mReviewCancelButton; - private Rotatable mReviewDoneButton; - private RotateImageView mReviewPlayButton; + private View mReviewCancelButton; + private View mReviewDoneButton; + private View mReviewPlayButton; private ShutterButton mShutterButton; private TextView mRecordingTimeView; private RotateLayout mBgLearningMessageRotater; @@ -414,13 +412,13 @@ public class VideoModule implements CameraModule, if (isVideoCaptureIntent()) { if (mReviewCancelButton != null) { - mGestures.addTouchReceiver((View) mReviewCancelButton); + mGestures.addTouchReceiver(mReviewCancelButton); } if (mReviewDoneButton != null) { - mGestures.addTouchReceiver((View) mReviewDoneButton); + mGestures.addTouchReceiver(mReviewDoneButton); } if (mReviewPlayButton != null) { - mGestures.addTouchReceiver((View) mReviewPlayButton); + mGestures.addTouchReceiver(mReviewPlayButton); } } } @@ -449,7 +447,7 @@ public class VideoModule implements CameraModule, mContentResolver = mActivity.getContentResolver(); - mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView); + mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView, true); // Surface texture is from camera screen nail and startPreview needs it. // This must be done before startPreview. @@ -589,8 +587,7 @@ public class VideoModule implements CameraModule, private void setOrientationIndicator(int orientation, boolean animation) { Rotatable[] indicators = { - mBgLearningMessageRotater, - mReviewDoneButton, mReviewPlayButton}; + mBgLearningMessageRotater}; for (Rotatable indicator : indicators) { if (indicator != null) indicator.setOrientation(orientation, animation); } @@ -598,14 +595,6 @@ public class VideoModule implements CameraModule, mGestures.setOrientation(orientation); } - // We change the orientation of the review cancel button only for tablet - // UI because there's a label along with the X icon. For phone UI, we - // don't change the orientation because there's only a symmetrical X - // icon. - if (mReviewCancelButton instanceof RotateLayout) { - mReviewCancelButton.setOrientation(orientation, animation); - } - // We change the orientation of the linearlayout only for phone UI because when in portrait // the width is not enough. if (mLabelsLinearLayout != null) { @@ -1636,7 +1625,6 @@ public class VideoModule implements CameraModule, mActivity.hideSwitcher(); mRecordingTimeView.setText(""); mRecordingTimeView.setVisibility(View.VISIBLE); - if (mReviewControl != null) mReviewControl.setVisibility(View.GONE); // The camera is not allowed to be accessed in older api levels during // recording. It is therefore necessary to hide the zoom UI on older // platforms. @@ -1650,7 +1638,6 @@ public class VideoModule implements CameraModule, mShutterButton.setImageResource(R.drawable.btn_new_shutter_video); mActivity.showSwitcher(); mRecordingTimeView.setVisibility(View.GONE); - if (mReviewControl != null) mReviewControl.setVisibility(View.VISIBLE); if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && mParameters.isZoomSupported()) { // TODO: enable zoom UI here. @@ -1679,7 +1666,7 @@ public class VideoModule implements CameraModule, Util.fadeOut(mShutterButton); - Util.fadeIn((View) mReviewDoneButton); + Util.fadeIn(mReviewDoneButton); Util.fadeIn(mReviewPlayButton); mMenu.setVisibility(View.GONE); mOnScreenIndicators.setVisibility(View.GONE); @@ -1695,7 +1682,7 @@ public class VideoModule implements CameraModule, mOnScreenIndicators.setVisibility(View.VISIBLE); enableCameraControls(true); - Util.fadeOut((View) mReviewDoneButton); + Util.fadeOut(mReviewDoneButton); Util.fadeOut(mReviewPlayButton); Util.fadeIn(mShutterButton); @@ -2115,8 +2102,8 @@ public class VideoModule implements CameraModule, } private void initializeControlByIntent() { - mBlocker = mRootView.findViewById(R.id.blocker); - mMenu = mRootView.findViewById(R.id.menu); + mBlocker = mActivity.findViewById(R.id.blocker); + mMenu = mActivity.findViewById(R.id.menu); mMenu.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -2125,46 +2112,40 @@ public class VideoModule implements CameraModule, } } }); - mOnScreenIndicators = mRootView.findViewById(R.id.on_screen_indicators); - mFlashIndicator = (ImageView) mRootView.findViewById(R.id.menu_flash_indicator); + mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators); + mFlashIndicator = (ImageView) mActivity.findViewById(R.id.menu_flash_indicator); if (mIsVideoCaptureIntent) { mActivity.hideSwitcher(); + ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls); + mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls); // Cannot use RotateImageView for "done" and "cancel" button because // the tablet layout uses RotateLayout, which cannot be cast to // RotateImageView. - mReviewDoneButton = (Rotatable) mRootView.findViewById(R.id.btn_done); - mReviewCancelButton = (Rotatable) mRootView.findViewById(R.id.btn_cancel); - mReviewPlayButton = (RotateImageView) mRootView.findViewById(R.id.btn_play); + mReviewDoneButton = mActivity.findViewById(R.id.btn_done); + mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); + mReviewPlayButton = mActivity.findViewById(R.id.btn_play); - ((View) mReviewCancelButton).setVisibility(View.VISIBLE); + mReviewCancelButton.setVisibility(View.VISIBLE); - ((View) mReviewDoneButton).setOnClickListener(new OnClickListener() { + mReviewDoneButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewDoneClicked(v); } }); - ((View) mReviewCancelButton).setOnClickListener(new OnClickListener() { + mReviewCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewCancelClicked(v); } }); - ((View) mReviewPlayButton).setOnClickListener(new OnClickListener() { + mReviewPlayButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewPlayClicked(v); } }); - - - // Not grayed out upon disabled, to make the follow-up fade-out - // effect look smooth. Note that the review done button in tablet - // layout is not a TwoStateImageView. - if (mReviewDoneButton instanceof TwoStateImageView) { - ((TwoStateImageView) mReviewDoneButton).enableFilter(false); - } } } @@ -2203,28 +2184,8 @@ public class VideoModule implements CameraModule, @Override public void onConfigurationChanged(Configuration newConfig) { + Log.v(TAG, "onConfigurationChanged"); setDisplayOrientation(); - // Change layout in response to configuration change - LayoutInflater inflater = mActivity.getLayoutInflater(); - ((ViewGroup) mRootView).removeAllViews(); - inflater.inflate(R.layout.video_module, (ViewGroup) mRootView); - - // from onCreate() - initializeControlByIntent(); - initializeOverlay(); - initializeSurfaceView(); - initializeMiscControls(); - showTimeLapseUI(mCaptureTimeLapse); - initializeVideoSnapshot(); - - // from onResume() - showVideoSnapshotUI(false); - initializeZoom(); - onFullScreenChanged(mActivity.isInCameraApp()); - updateOnScreenIndicators(); - if (mIsVideoCaptureIntent && mVideoFileDescriptor != null) { - showCaptureResult(); - } } @Override @@ -2784,6 +2745,11 @@ public class VideoModule implements CameraModule, return !mIsVideoCaptureIntent; } + @Override + public boolean needsPieMenu() { + return true; + } + @Override public void onPieOpened(int centerX, int centerY) { mActivity.cancelActivityTouchHandling(); diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java index 8d2cd7117..3fa4a01d5 100644 --- a/src/com/android/camera/ui/CameraSwitcher.java +++ b/src/com/android/camera/ui/CameraSwitcher.java @@ -30,6 +30,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; +import android.widget.FrameLayout.LayoutParams; import android.widget.LinearLayout; import com.android.gallery3d.R; @@ -177,6 +178,16 @@ public class CameraSwitcher extends RotateImageView mParent.setOnTouchListener(null); } + @Override + public void onConfigurationChanged(Configuration config) { + if (showsPopup()) { + ((ViewGroup) mParent).removeView(mPopup); + mPopup = null; + initPopup(); + mPopup.setVisibility(View.VISIBLE); + } + } + private void showSwitcher() { mShowingPopup = true; if (mPopup == null) { @@ -245,6 +256,8 @@ public class CameraSwitcher extends RotateImageView // Verify that we weren't canceled if (!showsPopup()) { mPopup.setVisibility(View.INVISIBLE); + ((ViewGroup) mParent).removeView(mPopup); + mPopup = null; } } }; diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java new file mode 100644 index 000000000..9c5ebd34d --- /dev/null +++ b/src/com/android/camera/ui/RotatableLayout.java @@ -0,0 +1,158 @@ +/* + * 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.content.res.Configuration; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +/* 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 { + + public RotatableLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public RotatableLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RotatableLayout(Context context) { + super(context); + } + + @Override + public void onConfigurationChanged(Configuration config) { + super.onConfigurationChanged(config); + // rotate the layout itself and all its children + boolean clockwise = (config.orientation == Configuration.ORIENTATION_PORTRAIT); + rotate(this, clockwise); + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + rotate(child, clockwise); + } + } + + 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); + } +} \ No newline at end of file -- cgit v1.2.3