summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/camera/ActivityBase.java25
-rw-r--r--src/com/android/camera/Camera.java91
-rw-r--r--src/com/android/camera/CameraSettings.java3
-rw-r--r--src/com/android/camera/ComboPreferences.java3
-rw-r--r--src/com/android/camera/EffectsRecorder.java18
-rw-r--r--src/com/android/camera/FocusManager.java22
-rw-r--r--src/com/android/camera/ListPreference.java35
-rw-r--r--src/com/android/camera/ModePicker.java18
-rw-r--r--src/com/android/camera/PreviewFrameLayout.java17
-rw-r--r--src/com/android/camera/RotateDialogController.java157
-rw-r--r--src/com/android/camera/Storage.java14
-rw-r--r--src/com/android/camera/Util.java2
-rwxr-xr-xsrc/com/android/camera/VideoCamera.java74
-rw-r--r--src/com/android/camera/panorama/MosaicRenderer.java3
-rw-r--r--src/com/android/camera/panorama/MosaicRendererSurfaceView.java25
-rwxr-xr-xsrc/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java7
-rwxr-xr-xsrc/com/android/camera/panorama/PanoramaActivity.java151
-rw-r--r--src/com/android/camera/ui/AbstractIndicatorButton.java6
-rw-r--r--src/com/android/camera/ui/ControlPanelLayout.java47
-rw-r--r--src/com/android/camera/ui/EffectSettingPopup.java14
-rw-r--r--src/com/android/camera/ui/FaceView.java2
-rw-r--r--src/com/android/camera/ui/IndicatorControl.java14
-rw-r--r--src/com/android/camera/ui/IndicatorControlBar.java15
-rw-r--r--src/com/android/camera/ui/IndicatorControlBarContainer.java14
-rw-r--r--src/com/android/camera/ui/IndicatorControlWheel.java59
-rw-r--r--src/com/android/camera/ui/IndicatorControlWheelContainer.java8
-rw-r--r--src/com/android/camera/ui/OneRowGridView.java43
-rw-r--r--src/com/android/camera/ui/RightAlignedHorizontalScrollView.java44
-rw-r--r--src/com/android/camera/ui/RotateImageView.java8
-rw-r--r--src/com/android/camera/ui/RotateLayout.java2
-rw-r--r--src/com/android/camera/ui/SecondLevelIndicatorControlBar.java70
-rw-r--r--src/com/android/camera/ui/SharePopup.java19
-rw-r--r--src/com/android/camera/ui/ZoomControl.java10
-rw-r--r--src/com/android/camera/ui/ZoomControlBar.java56
34 files changed, 810 insertions, 286 deletions
diff --git a/src/com/android/camera/ActivityBase.java b/src/com/android/camera/ActivityBase.java
index b2ef481..ea523c8 100644
--- a/src/com/android/camera/ActivityBase.java
+++ b/src/com/android/camera/ActivityBase.java
@@ -20,13 +20,14 @@ import com.android.camera.ui.PopupManager;
import android.app.Activity;
import android.app.KeyguardManager;
-import android.view.KeyEvent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
+import android.view.KeyEvent;
/**
* Superclass of Camera and VideoCamera activities.
@@ -41,6 +42,11 @@ abstract public class ActivityBase extends Activity {
@Override
public void onCreate(Bundle icicle) {
+ if (Util.isTabletUI()) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
super.onCreate(icicle);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
@@ -61,11 +67,16 @@ abstract public class ActivityBase extends Activity {
// Don't grab the camera if in use by lockscreen. For example, face
// unlock may be using the camera. Camera may be already opened in
// onCreate. doOnResume should continue if mCameraDevice != null.
- if (mCameraDevice == null && !hasWindowFocus() && isKeyguardLocked()) {
- if (LOGV) Log.v(TAG, "onRsume. mOnResumePending=true");
+ // Suppose camera app is in the foreground. If users turn off and turn
+ // on the screen very fast, camera app can still have the focus when the
+ // lock screen shows up. The keyguard takes input focus, so the caemra
+ // app will lose focus when it is displayed.
+ if (LOGV) Log.v(TAG, "onResume. hasWindowFocus()=" + hasWindowFocus());
+ if (mCameraDevice == null && isKeyguardLocked()) {
+ if (LOGV) Log.v(TAG, "onResume. mOnResumePending=true");
mOnResumePending = true;
} else {
- if (LOGV) Log.v(TAG, "onRsume. mOnResumePending=false");
+ if (LOGV) Log.v(TAG, "onResume. mOnResumePending=false");
doOnResume();
mOnResumePending = false;
}
@@ -124,6 +135,12 @@ abstract public class ActivityBase extends Activity {
private boolean isKeyguardLocked() {
KeyguardManager kgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ if (LOGV) {
+ if (kgm != null) {
+ Log.v(TAG, "kgm.isKeyguardLocked()="+kgm.isKeyguardLocked()
+ + ". kgm.isKeyguardSecure()="+kgm.isKeyguardSecure());
+ }
+ }
// isKeyguardSecure excludes the slide lock case.
return (kgm != null) && kgm.isKeyguardLocked() && kgm.isKeyguardSecure();
}
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 8898510..9c7bbfe 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -33,6 +33,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences.Editor;
+import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Face;
@@ -62,6 +63,7 @@ import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
@@ -145,6 +147,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
private View mPreviewPanel; // The container of PreviewFrameLayout.
private PreviewFrameLayout mPreviewFrameLayout;
private View mPreviewFrame; // Preview frame area.
+ private RotateDialogController mRotateDialog;
// A popup window that contains a bigger thumbnail and a list of apps to share.
private SharePopup mSharePopup;
@@ -188,7 +191,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
*
* TODO: consider publishing by moving into MediaStore.
*/
- private final static String EXTRA_QUICK_CAPTURE =
+ private static final String EXTRA_QUICK_CAPTURE =
"android.intent.extra.quickCapture";
// The display rotation in degrees. This is only valid when mCameraState is
@@ -303,7 +306,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
}
case DISMISS_TAP_TO_FOCUS_TOAST: {
- View v = findViewById(R.id.tap_to_focus_prompt);
+ View v = findViewById(R.id.first_use_hint);
v.setVisibility(View.GONE);
v.setAnimation(AnimationUtils.loadAnimation(Camera.this,
R.anim.on_screen_hint_exit));
@@ -388,7 +391,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
startFaceDetection();
// Show the tap to focus toast if this is the first start.
if (mFocusAreaSupported &&
- mPreferences.getBoolean(CameraSettings.KEY_TAP_TO_FOCUS_PROMPT_SHOWN, true)) {
+ mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) {
// Delay the toast for one second to wait for orientation.
mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000);
}
@@ -698,8 +701,6 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
+ mPictureDisplayedToJpegCallbackTime + "ms");
if (!mIsImageCaptureIntent) {
- enableCameraControls(true);
-
startPreview();
startFaceDetection();
}
@@ -738,12 +739,8 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime;
Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms");
+ setCameraState(IDLE);
mFocusManager.onAutoFocus(focused);
- // If focus completes and the snapshot is not started, enable the
- // controls.
- if (mFocusManager.isFocusCompleted()) {
- enableCameraControls(true);
- }
}
}
@@ -823,7 +820,11 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
r.width = width;
r.height = height;
r.dateTaken = System.currentTimeMillis();
- r.previewWidth = mPreviewFrameLayout.getWidth();
+ if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ r.previewWidth = mPreviewFrameLayout.getHeight();
+ } else {
+ r.previewWidth = mPreviewFrameLayout.getWidth();
+ }
synchronized (this) {
while (mQueue.size() >= QUEUE_LIMIT) {
try {
@@ -949,6 +950,20 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
}
}
+ private void setCameraState(int state) {
+ mCameraState = state;
+ switch (state) {
+ case SNAPSHOT_IN_PROGRESS:
+ case FOCUSING:
+ enableCameraControls(false);
+ break;
+ case IDLE:
+ case PREVIEW_STOPPED:
+ enableCameraControls(true);
+ break;
+ }
+ }
+
@Override
public boolean capture() {
// If we are already in the middle of taking a snapshot then ignore.
@@ -957,7 +972,6 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
}
mCaptureStartTime = System.currentTimeMillis();
mPostViewPictureCallbackTime = 0;
- enableCameraControls(false);
mJpegImageData = null;
// Set rotation and gps data.
@@ -968,7 +982,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback,
mPostViewPictureCallback, new JpegPictureCallback(loc));
- mCameraState = SNAPSHOT_IN_PROGRESS;
+ setCameraState(SNAPSHOT_IN_PROGRESS);
return true;
}
@@ -1025,8 +1039,9 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getPreferredCameraId();
- mFocusManager = new FocusManager(mPreferences,
- getString(R.string.pref_camera_focusmode_default));
+ String[] defaultFocusModes = getResources().getStringArray(
+ R.array.pref_camera_focusmode_default_array);
+ mFocusManager = new FocusManager(mPreferences, defaultFocusModes);
/*
* To reduce startup time, we start the camera open and preview threads.
@@ -1046,6 +1061,8 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
mThumbnailView.setVisibility(View.VISIBLE);
}
+ mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog);
+
mPreferences.setLocalId(this, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
@@ -1216,16 +1233,13 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
}
}
- private void setOrientationIndicator(int degree) {
- if (mThumbnailView != null) mThumbnailView.setDegree(degree);
- if (mModePicker != null) mModePicker.setDegree(degree);
- if (mSharePopup != null) mSharePopup.setOrientation(degree);
- if (mIndicatorControlContainer != null) mIndicatorControlContainer.setDegree(degree);
- if (mZoomControl != null) mZoomControl.setDegree(degree);
- if (mFocusIndicator != null) mFocusIndicator.setOrientation(degree);
- if (mFaceView != null) mFaceView.setOrientation(degree);
- if (mReviewCancelButton != null) mReviewCancelButton.setOrientation(degree);
- if (mReviewDoneButton != null) mReviewDoneButton.setOrientation(degree);
+ private void setOrientationIndicator(int orientation) {
+ Rotatable[] indicators = {mThumbnailView, mModePicker, mSharePopup,
+ mIndicatorControlContainer, mZoomControl, mFocusIndicator, mFaceView,
+ mReviewCancelButton, mReviewDoneButton, mRotateDialog};
+ for (Rotatable indicator : indicators) {
+ if (indicator != null) indicator.setOrientation(orientation);
+ }
}
@Override
@@ -1437,7 +1451,6 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
if (mOpenCameraFail || mCameraDisabled) return;
mPausing = false;
-
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
@@ -1556,15 +1569,13 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
public void autoFocus() {
mFocusStartTime = System.currentTimeMillis();
mCameraDevice.autoFocus(mAutoFocusCallback);
- mCameraState = FOCUSING;
- enableCameraControls(false);
+ setCameraState(FOCUSING);
}
@Override
public void cancelAutoFocus() {
mCameraDevice.cancelAutoFocus();
- mCameraState = IDLE;
- enableCameraControls(true);
+ setCameraState(IDLE);
setCameraParameters(UPDATE_PARAM_PREFERENCE);
}
@@ -1710,7 +1721,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
mCameraDevice.setFaceDetectionListener(null);
mCameraDevice.setErrorCallback(null);
mCameraDevice = null;
- mCameraState = PREVIEW_STOPPED;
+ setCameraState(PREVIEW_STOPPED);
mFocusManager.onCameraReleased();
}
}
@@ -1771,7 +1782,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
}
mZoomState = ZOOM_STOPPED;
- mCameraState = IDLE;
+ setCameraState(IDLE);
mFocusManager.onPreviewStarted();
if (mSnapshotOnIdle) {
@@ -1785,7 +1796,7 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
mCameraDevice.cancelAutoFocus(); // Reset the focus.
mCameraDevice.stopPreview();
}
- mCameraState = PREVIEW_STOPPED;
+ setCameraState(PREVIEW_STOPPED);
mFocusManager.onPreviewStopped();
}
@@ -2026,8 +2037,6 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
private void hidePostCaptureAlert() {
if (mIsImageCaptureIntent) {
- enableCameraControls(true);
-
int[] pickIds = {R.id.btn_retake, R.id.btn_done};
for (int id : pickIds) {
Util.fadeOut(findViewById(id));
@@ -2158,10 +2167,11 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
restorePreferences();
}
};
- MenuHelper.confirmAction(this,
+ mRotateDialog.showAlertDialog(
getString(R.string.confirm_restore_title),
getString(R.string.confirm_restore_message),
- runnable);
+ getString(android.R.string.ok), runnable,
+ getString(android.R.string.cancel), null);
}
private void restorePreferences() {
@@ -2206,15 +2216,18 @@ public class Camera extends ActivityBase implements FocusManager.Listener,
}
private void showTapToFocusToast() {
+ // Set the text of toast
+ TextView textView = (TextView) findViewById(R.id.toast_text);
+ textView.setText(R.string.tap_to_focus);
// Show the toast.
- RotateLayout v = (RotateLayout) findViewById(R.id.tap_to_focus_prompt);
+ RotateLayout v = (RotateLayout) findViewById(R.id.first_use_hint);
v.setOrientation(mOrientationCompensation);
v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.on_screen_hint_enter));
v.setVisibility(View.VISIBLE);
mHandler.sendEmptyMessageDelayed(DISMISS_TAP_TO_FOCUS_TOAST, 5000);
// Clear the preference.
Editor editor = mPreferences.edit();
- editor.putBoolean(CameraSettings.KEY_TAP_TO_FOCUS_PROMPT_SHOWN, false);
+ editor.putBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, false);
editor.apply();
}
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 9c3104b..c861366 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -50,7 +50,8 @@ public class CameraSettings {
public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
public static final String KEY_VIDEO_EFFECT = "pref_video_effect_key";
public static final String KEY_CAMERA_ID = "pref_camera_id_key";
- public static final String KEY_TAP_TO_FOCUS_PROMPT_SHOWN = "pref_tap_to_focus_prompt_shown_key";
+ public static final String KEY_CAMERA_FIRST_USE_HINT_SHOWN = "pref_camera_first_use_hint_shown_key";
+ public static final String KEY_VIDEO_FIRST_USE_HINT_SHOWN = "pref_video_first_use_hint_shown_key";
public static final String EXPOSURE_DEFAULT_VALUE = "0";
diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java
index 1af634c..bea2ffd 100644
--- a/src/com/android/camera/ComboPreferences.java
+++ b/src/com/android/camera/ComboPreferences.java
@@ -76,7 +76,8 @@ public class ComboPreferences implements SharedPreferences, OnSharedPreferenceCh
return key.equals(CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL)
|| key.equals(CameraSettings.KEY_CAMERA_ID)
|| key.equals(CameraSettings.KEY_RECORD_LOCATION)
- || key.equals(CameraSettings.KEY_TAP_TO_FOCUS_PROMPT_SHOWN)
+ || key.equals(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN)
+ || key.equals(CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN)
|| key.equals(CameraSettings.KEY_VIDEO_EFFECT);
}
diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java
index d5f83ef..bb7c813 100644
--- a/src/com/android/camera/EffectsRecorder.java
+++ b/src/com/android/camera/EffectsRecorder.java
@@ -93,6 +93,7 @@ public class EffectsRecorder {
private long mMaxFileSize = 0;
private int mMaxDurationMs = 0;
private int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
+ private boolean mAppIsLandscape;
private int mEffect = EFFECT_NONE;
private int mCurrentEffect = EFFECT_NONE;
@@ -375,6 +376,16 @@ public class EffectsRecorder {
setRecordingOrientation();
}
+ /** Passes the native orientation of the Camera app (device dependent)
+ * to allow for correct output aspect ratio. Defaults to portrait */
+ public void setAppToLandscape(boolean landscape) {
+ if (mState != STATE_CONFIGURE) {
+ throw new RuntimeException(
+ "setAppToLandscape called after configuration!");
+ }
+ mAppIsLandscape = landscape;
+ }
+
public void setCameraFacing(int facing) {
switch (mState) {
case STATE_RELEASED:
@@ -419,7 +430,12 @@ public class EffectsRecorder {
Log.v(TAG, "Effects framework initializing. Recording size "
+ mProfile.videoFrameWidth + ", " + mProfile.videoFrameHeight);
}
-
+ if (!mAppIsLandscape) {
+ int tmp;
+ tmp = mProfile.videoFrameWidth;
+ mProfile.videoFrameWidth = mProfile.videoFrameHeight;
+ mProfile.videoFrameHeight = tmp;
+ }
mGraphEnv.addReferences(
"textureSourceCallback", mSourceReadyCallback,
"recordingWidth", mProfile.videoFrameWidth,
diff --git a/src/com/android/camera/FocusManager.java b/src/com/android/camera/FocusManager.java
index 72ea8b5..bdf4766 100644
--- a/src/com/android/camera/FocusManager.java
+++ b/src/com/android/camera/FocusManager.java
@@ -67,7 +67,7 @@ public class FocusManager {
private List<Area> mFocusArea; // focus area in driver format
private List<Area> mMeteringArea; // metering area in driver format
private String mFocusMode;
- private String mDefaultFocusMode;
+ private String[] mDefaultFocusModes;
private String mOverrideFocusMode;
private Parameters mParameters;
private ComboPreferences mPreferences;
@@ -96,9 +96,9 @@ public class FocusManager {
}
}
- public FocusManager(ComboPreferences preferences, String defaultFocusMode) {
+ public FocusManager(ComboPreferences preferences, String[] defaultFocusModes) {
mPreferences = preferences;
- mDefaultFocusMode = defaultFocusMode;
+ mDefaultFocusModes = defaultFocusModes;
mHandler = new MainHandler();
mMatrix = new Matrix();
}
@@ -361,6 +361,7 @@ public class FocusManager {
// This can only be called after mParameters is initialized.
public String getFocusMode() {
if (mOverrideFocusMode != null) return mOverrideFocusMode;
+ List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
if (mFocusAreaSupported && mFocusArea != null) {
// Always use autofocus in tap-to-focus.
@@ -368,9 +369,20 @@ public class FocusManager {
} else {
// The default is continuous autofocus.
mFocusMode = mPreferences.getString(
- CameraSettings.KEY_FOCUS_MODE, mDefaultFocusMode);
+ CameraSettings.KEY_FOCUS_MODE, null);
+
+ // Try to find a supported focus mode from the default list.
+ if (mFocusMode == null) {
+ for (int i = 0; i < mDefaultFocusModes.length; i++) {
+ String mode = mDefaultFocusModes[i];
+ if (isSupported(mode, supportedFocusModes)) {
+ mFocusMode = mode;
+ break;
+ }
+ }
+ }
}
- if (!isSupported(mFocusMode, mParameters.getSupportedFocusModes())) {
+ if (!isSupported(mFocusMode, supportedFocusModes)) {
// For some reasons, the driver does not support the current
// focus mode. Fall back to auto.
if (isSupported(Parameters.FOCUS_MODE_AUTO,
diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java
index 6885a37..32cf692 100644
--- a/src/com/android/camera/ListPreference.java
+++ b/src/com/android/camera/ListPreference.java
@@ -21,6 +21,7 @@ import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.TypedValue;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +34,7 @@ public class ListPreference extends CameraPreference {
private final String TAG = "ListPreference";
private final String mKey;
private String mValue;
- private final String mDefaultValue;
+ private final CharSequence[] mDefaultValues;
private CharSequence[] mEntries;
private CharSequence[] mEntryValues;
@@ -47,7 +48,20 @@ public class ListPreference extends CameraPreference {
mKey = Util.checkNotNull(
a.getString(R.styleable.ListPreference_key));
- mDefaultValue = a.getString(R.styleable.ListPreference_defaultValue);
+
+ // We allow the defaultValue attribute to be a string or an array of
+ // strings. The reason we need multiple default values is that some
+ // of them may be unsupported on a specific platform (for example,
+ // continuous auto-focus). In that case the first supported value
+ // in the array will be used.
+ int attrDefaultValue = R.styleable.ListPreference_defaultValue;
+ TypedValue tv = a.peekValue(attrDefaultValue);
+ if (tv != null && tv.type == TypedValue.TYPE_REFERENCE) {
+ mDefaultValues = a.getTextArray(attrDefaultValue);
+ } else {
+ mDefaultValues = new CharSequence[1];
+ mDefaultValues[0] = a.getString(attrDefaultValue);
+ }
setEntries(a.getTextArray(R.styleable.ListPreference_entries));
setEntryValues(a.getTextArray(
@@ -77,12 +91,27 @@ public class ListPreference extends CameraPreference {
public String getValue() {
if (!mLoaded) {
- mValue = getSharedPreferences().getString(mKey, mDefaultValue);
+ mValue = getSharedPreferences().getString(mKey,
+ findSupportedDefaultValue());
mLoaded = true;
}
return mValue;
}
+ // Find the first value in mDefaultValues which is supported.
+ private String findSupportedDefaultValue() {
+ for (int i = 0; i < mDefaultValues.length; i++) {
+ for (int j = 0; j < mEntryValues.length; j++) {
+ // Note that mDefaultValues[i] may be null (if unspecified
+ // in the xml file).
+ if (mEntryValues[j].equals(mDefaultValues[i])) {
+ return mDefaultValues[i].toString();
+ }
+ }
+ }
+ return null;
+ }
+
public void setValue(String value) {
if (findIndexOfValue(value) < 0) throw new IllegalArgumentException();
mValue = value;
diff --git a/src/com/android/camera/ModePicker.java b/src/com/android/camera/ModePicker.java
index 528bc3d..b79baa5 100644
--- a/src/com/android/camera/ModePicker.java
+++ b/src/com/android/camera/ModePicker.java
@@ -17,6 +17,7 @@
package com.android.camera;
import com.android.camera.ui.PopupManager;
+import com.android.camera.ui.Rotatable;
import com.android.camera.ui.RotateImageView;
import android.content.Context;
@@ -36,7 +37,7 @@ import android.widget.RelativeLayout;
* a current mode indicator.
*/
public class ModePicker extends RelativeLayout implements View.OnClickListener,
- PopupManager.OnOtherPopupShowedListener {
+ PopupManager.OnOtherPopupShowedListener, Rotatable {
public static final int MODE_CAMERA = 0;
public static final int MODE_VIDEO = 1;
public static final int MODE_PANORAMA = 2;
@@ -188,11 +189,11 @@ public class ModePicker extends RelativeLayout implements View.OnClickListener,
return true;
}
- public void setDegree(int degree) {
+ public void setOrientation(int orientation) {
for (int i = 0; i < MODE_NUM; ++i) {
- mModeSelectionIcon[i].setDegree(degree);
+ mModeSelectionIcon[i].setOrientation(orientation);
if (mCurrentModeFrame != null) {
- mCurrentModeIcon[i].setDegree(degree);
+ mCurrentModeIcon[i].setOrientation(orientation);
}
}
}
@@ -222,10 +223,13 @@ public class ModePicker extends RelativeLayout implements View.OnClickListener,
}
private void updateModeState() {
- // Grey-out the unselected icons.
- for (int i = 0; i < MODE_NUM; ++i) {
- highlightView(mModeSelectionIcon[i], (i == mCurrentMode));
+ // Grey-out the unselected icons for Phone UI.
+ if (mCurrentModeFrame != null) {
+ for (int i = 0; i < MODE_NUM; ++i) {
+ highlightView(mModeSelectionIcon[i], (i == mCurrentMode));
+ }
}
+
// Update the current mode icons on the Phone UI. The selected mode
// should be in the center of the current mode icon bar.
if (mCurrentModeFrame != null) {
diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java
index 5d31e2b..c16961a 100644
--- a/src/com/android/camera/PreviewFrameLayout.java
+++ b/src/com/android/camera/PreviewFrameLayout.java
@@ -18,8 +18,10 @@ package com.android.camera;
import com.android.camera.R;
+import android.app.Activity;
import android.content.Context;
-import android.graphics.Rect;
+import android.content.pm.ActivityInfo;
+import android.view.View;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
/**
@@ -31,14 +33,21 @@ public class PreviewFrameLayout extends RelativeLayout {
public void onSizeChanged();
}
- private double mAspectRatio = 4.0 / 3.0;
+ private double mAspectRatio;
public PreviewFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
+ setAspectRatio(4.0 / 3.0);
}
public void setAspectRatio(double ratio) {
if (ratio <= 0.0) throw new IllegalArgumentException();
+
+ if (((Activity) getContext()).getRequestedOrientation()
+ == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ ratio = 1 / ratio;
+ }
+
if (mAspectRatio != ratio) {
mAspectRatio = ratio;
requestLayout();
@@ -46,10 +55,10 @@ public class PreviewFrameLayout extends RelativeLayout {
}
public void showBorder(boolean enabled) {
- setActivated(enabled);
+ findViewById(R.id.preview_border).setVisibility(
+ enabled ? View.VISIBLE : View.INVISIBLE);
}
-
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
int previewWidth = MeasureSpec.getSize(widthSpec);
diff --git a/src/com/android/camera/RotateDialogController.java b/src/com/android/camera/RotateDialogController.java
new file mode 100644
index 0000000..d91ba13
--- /dev/null
+++ b/src/com/android/camera/RotateDialogController.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 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 com.android.camera.ui.Rotatable;
+import com.android.camera.ui.RotateLayout;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.ProgressBar;
+
+public class RotateDialogController implements Rotatable {
+
+ private static final String TAG = "RotateDialogController";
+ private static final long ANIM_DURATION = 150; // millis
+
+ private Activity mActivity;
+ private int mLayoutResourceID;
+ private View mDialogRootLayout;
+ private RotateLayout mRotateDialog;
+ private View mRotateDialogTitleLayout;
+ private View mRotateDialogButtonLayout;
+ private TextView mRotateDialogTitle;
+ private ProgressBar mRotateDialogSpinner;
+ private TextView mRotateDialogText;
+ private TextView mRotateDialogButton1;
+ private TextView mRotateDialogButton2;
+
+ private Animation mFadeInAnim, mFadeOutAnim;
+
+ public RotateDialogController(Activity a, int layoutResource) {
+ mActivity = a;
+ mLayoutResourceID = layoutResource;
+ }
+
+ private void inflateDialogLayout() {
+ if (mDialogRootLayout == null) {
+ ViewGroup layoutRoot = (ViewGroup) mActivity.getWindow().getDecorView();
+ LayoutInflater inflater = mActivity.getLayoutInflater();
+ View v = inflater.inflate(mLayoutResourceID, layoutRoot);
+ mDialogRootLayout = v.findViewById(R.id.rotate_dialog_root_layout);
+ mRotateDialog = (RotateLayout) v.findViewById(R.id.rotate_dialog_layout);
+ mRotateDialogTitleLayout = v.findViewById(R.id.rotate_dialog_title_layout);
+ mRotateDialogButtonLayout = v.findViewById(R.id.rotate_dialog_button_layout);
+ mRotateDialogTitle = (TextView) v.findViewById(R.id.rotate_dialog_title);
+ mRotateDialogSpinner = (ProgressBar) v.findViewById(R.id.rotate_dialog_spinner);
+ mRotateDialogText = (TextView) v.findViewById(R.id.rotate_dialog_text);
+ mRotateDialogButton1 = (Button) v.findViewById(R.id.rotate_dialog_button1);
+ mRotateDialogButton2 = (Button) v.findViewById(R.id.rotate_dialog_button2);
+
+ mFadeInAnim = AnimationUtils.loadAnimation(
+ mActivity, android.R.anim.fade_in);
+ mFadeOutAnim = AnimationUtils.loadAnimation(
+ mActivity, android.R.anim.fade_out);
+ mFadeInAnim.setDuration(ANIM_DURATION);
+ mFadeOutAnim.setDuration(ANIM_DURATION);
+ }
+ }
+
+ @Override
+ public void setOrientation(int orientation) {
+ inflateDialogLayout();
+ mRotateDialog.setOrientation(orientation);
+ }
+
+ public void resetRotateDialog() {
+ inflateDialogLayout();
+ mRotateDialogTitleLayout.setVisibility(View.GONE);
+ mRotateDialogSpinner.setVisibility(View.GONE);
+ mRotateDialogButton1.setVisibility(View.GONE);
+ mRotateDialogButton2.setVisibility(View.GONE);
+ mRotateDialogButtonLayout.setVisibility(View.GONE);
+ }
+
+ private void fadeOutDialog() {
+ mDialogRootLayout.startAnimation(mFadeOutAnim);
+ mDialogRootLayout.setVisibility(View.GONE);
+ }
+
+ private void fadeInDialog() {
+ mDialogRootLayout.startAnimation(mFadeInAnim);
+ mDialogRootLayout.setVisibility(View.VISIBLE);
+ }
+
+ public void dismissDialog() {
+ if (mDialogRootLayout != null && mDialogRootLayout.getVisibility() != View.GONE) {
+ fadeOutDialog();
+ }
+ }
+
+ public void showAlertDialog(String title, String msg, String button1Text,
+ final Runnable r1, String button2Text, final Runnable r2) {
+ resetRotateDialog();
+
+ mRotateDialogTitle.setText(title);
+ mRotateDialogTitleLayout.setVisibility(View.VISIBLE);
+
+ mRotateDialogText.setText(msg);
+
+ if (button1Text != null) {
+ mRotateDialogButton1.setText(button1Text);
+ mRotateDialogButton1.setVisibility(View.VISIBLE);
+ mRotateDialogButton1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (r1 != null) r1.run();
+ dismissDialog();
+ }
+ });
+ mRotateDialogButtonLayout.setVisibility(View.VISIBLE);
+ }
+ if (button2Text != null) {
+ mRotateDialogButton2.setText(button2Text);
+ mRotateDialogButton2.setVisibility(View.VISIBLE);
+ mRotateDialogButton2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (r2 != null) r2.run();
+ dismissDialog();
+ }
+ });
+ mRotateDialogButtonLayout.setVisibility(View.VISIBLE);
+ }
+
+ fadeInDialog();
+ }
+
+ public void showWaitingDialog(String msg) {
+ resetRotateDialog();
+
+ mRotateDialogText.setText(msg);
+ mRotateDialogSpinner.setVisibility(View.VISIBLE);
+
+ fadeInDialog();
+ }
+
+}
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index 564c088..38a6d48 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -84,10 +84,16 @@ public class Storage {
values.put(ImageColumns.LONGITUDE, location.getLongitude());
}
- Uri uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
- if (uri == null) {
- Log.e(TAG, "Failed to write MediaStore");
- return null;
+ Uri uri = null;
+ try {
+ uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
+ } catch (Throwable th) {
+ // This can happen when the external volume is already mounted, but
+ // MediaScanner has not notify MediaProvider to add that volume.
+ // The picture is still safe and MediaScanner will find it and
+ // insert it into MediaProvider. The only problem is that the user
+ // cannot click the thumbnail to review the picture.
+ Log.e(TAG, "Failed to write MediaStore" + th);
}
return uri;
}
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index 21bad6f..ba8a4f7 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -90,7 +90,7 @@ public class Util {
}
public static void initialize(Context context) {
- sIsTabletUI = (context.getResources().getConfiguration().screenWidthDp >= 1024);
+ sIsTabletUI = (context.getResources().getConfiguration().smallestScreenWidthDp >= 600);
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager)
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 6de5a81..0b946c4 100755
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -32,6 +32,8 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.hardware.Camera.CameraInfo;
@@ -64,6 +66,7 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -94,6 +97,8 @@ public class VideoCamera extends ActivityBase
private static final int CLEAR_SCREEN_DELAY = 4;
private static final int UPDATE_RECORD_TIME = 5;
private static final int ENABLE_SHUTTER_BUTTON = 6;
+ private static final int SHOW_TAP_TO_SNAPSHOT_TOAST = 7;
+ private static final int DISMISS_TAP_TO_SNAPSHOT_TOAST = 8;
private static final int SCREEN_DELAY = 2 * 60 * 1000;
@@ -111,7 +116,7 @@ public class VideoCamera extends ActivityBase
CamcorderProfile.QUALITY_TIME_LAPSE_720P,
CamcorderProfile.QUALITY_TIME_LAPSE_480P,
CamcorderProfile.QUALITY_TIME_LAPSE_CIF,
- 1007, /* TODO: replace it with QUALITY_TIME_LAPSE_QVGA if public. */
+ CamcorderProfile.QUALITY_TIME_LAPSE_QVGA,
CamcorderProfile.QUALITY_TIME_LAPSE_QCIF};
private static final int[] VIDEO_QUALITY = {
@@ -119,7 +124,7 @@ public class VideoCamera extends ActivityBase
CamcorderProfile.QUALITY_720P,
CamcorderProfile.QUALITY_480P,
CamcorderProfile.QUALITY_CIF,
- 7, /* TODO: replace it with CamcorderProfile.QUALITY_QVGA */
+ CamcorderProfile.QUALITY_QVGA,
CamcorderProfile.QUALITY_QCIF};
/**
@@ -297,6 +302,19 @@ public class VideoCamera extends ActivityBase
break;
}
+ case SHOW_TAP_TO_SNAPSHOT_TOAST: {
+ showTapToSnapshotToast();
+ break;
+ }
+
+ case DISMISS_TAP_TO_SNAPSHOT_TOAST: {
+ View v = findViewById(R.id.first_use_hint);
+ v.setVisibility(View.GONE);
+ v.setAnimation(AnimationUtils.loadAnimation(VideoCamera.this,
+ R.anim.on_screen_hint_exit));
+ break;
+ }
+
default:
Log.v(TAG, "Unhandled message: " + msg.what);
break;
@@ -539,22 +557,27 @@ public class VideoCamera extends ActivityBase
setOrientationIndicator(mOrientationCompensation);
}
}
+
+ // Show the toast after getting the first orientation changed.
+ if (mHandler.hasMessages(SHOW_TAP_TO_SNAPSHOT_TOAST)) {
+ mHandler.removeMessages(SHOW_TAP_TO_SNAPSHOT_TOAST);
+ showTapToSnapshotToast();
+ }
}
}
- private void setOrientationIndicator(int degree) {
- if (mThumbnailView != null) mThumbnailView.setDegree(degree);
- if (mModePicker != null) mModePicker.setDegree(degree);
- if (mSharePopup != null) mSharePopup.setOrientation(degree);
- if (mBgLearningMessageRotater != null) mBgLearningMessageRotater.setOrientation(degree);
- if (mIndicatorControlContainer != null) mIndicatorControlContainer.setDegree(degree);
- if (mReviewDoneButton != null) mReviewDoneButton.setOrientation(degree);
- if (mReviewPlayButton != null) mReviewPlayButton.setOrientation(degree);
- if (mReviewCancelButton!= null) mReviewCancelButton.setOrientation(degree);
+ private void setOrientationIndicator(int orientation) {
+ Rotatable[] indicators = {mThumbnailView, mModePicker, mSharePopup,
+ mBgLearningMessageRotater, mIndicatorControlContainer,
+ mReviewDoneButton, mReviewPlayButton, mReviewCancelButton};
+ for (Rotatable indicator : indicators) {
+ if (indicator != null) indicator.setOrientation(orientation);
+ }
+
// We change the orientation of the linearlayout only for phone UI because when in portrait
// the width is not enough.
if (mLabelsLinearLayout != null) {
- if (((degree / 90) & 1) == 1) {
+ if (((orientation / 90) & 1) == 1) {
mLabelsLinearLayout.setOrientation(mLabelsLinearLayout.VERTICAL);
} else {
mLabelsLinearLayout.setOrientation(mLabelsLinearLayout.HORIZONTAL);
@@ -1238,6 +1261,10 @@ public class VideoCamera extends ActivityBase
// If the mCameraDevice is null, then this activity is going to finish
if (mCameraDevice == null) return;
+ boolean inLandscape =
+ (getRequestedOrientation() ==
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+
CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
mEffectsDisplayResult = false;
@@ -1245,6 +1272,7 @@ public class VideoCamera extends ActivityBase
// TODO: Confirm none of the foll need to go to initializeEffectsRecording()
// and none of these change even when the preview is not refreshed.
+ mEffectsRecorder.setAppToLandscape(inLandscape);
mEffectsRecorder.setCamera(mCameraDevice);
mEffectsRecorder.setCameraFacing(info.facing);
mEffectsRecorder.setProfile(mProfile);
@@ -2290,6 +2318,12 @@ public class VideoCamera extends ActivityBase
private void initializeVideoSnapshot() {
if (mParameters.isVideoSnapshotSupported() && !mIsVideoCaptureIntent) {
findViewById(R.id.camera_preview).setOnTouchListener(this);
+ // Show the tap to focus toast if this is the first start.
+ if (mPreferences.getBoolean(
+ CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN, true)) {
+ // Delay the toast for one second to wait for orientation.
+ mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_SNAPSHOT_TOAST, 1000);
+ }
}
}
@@ -2403,4 +2437,20 @@ public class VideoCamera extends ActivityBase
mVideoFileDescriptor = null;
}
}
+
+ private void showTapToSnapshotToast() {
+ // Set the text of toast
+ TextView textView = (TextView) findViewById(R.id.toast_text);
+ textView.setText(R.string.video_snapshot_hint);
+ // Show the toast.
+ RotateLayout v = (RotateLayout) findViewById(R.id.first_use_hint);
+ v.setOrientation(mOrientationCompensation);
+ v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.on_screen_hint_enter));
+ v.setVisibility(View.VISIBLE);
+ mHandler.sendEmptyMessageDelayed(DISMISS_TAP_TO_SNAPSHOT_TOAST, 5000);
+ // Clear the preference.
+ Editor editor = mPreferences.edit();
+ editor.putBoolean(CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN, false);
+ editor.apply();
+ }
}
diff --git a/src/com/android/camera/panorama/MosaicRenderer.java b/src/com/android/camera/panorama/MosaicRenderer.java
index 1ff307d..f055c0e 100644
--- a/src/com/android/camera/panorama/MosaicRenderer.java
+++ b/src/com/android/camera/panorama/MosaicRenderer.java
@@ -43,8 +43,9 @@ public class MosaicRenderer
*
* @param width width of the drawing surface in pixels.
* @param height height of the drawing surface in pixels.
+ * @param isLandscapeOrientation is the orientation of the activity layout in landscape.
*/
- public static native void reset(int width, int height);
+ public static native void reset(int width, int height, boolean isLandscapeOrientation);
/**
* Calling this function will render the SurfaceTexture to a new 2D texture
diff --git a/src/com/android/camera/panorama/MosaicRendererSurfaceView.java b/src/com/android/camera/panorama/MosaicRendererSurfaceView.java
index 08d4eff..b2acfde 100644
--- a/src/com/android/camera/panorama/MosaicRendererSurfaceView.java
+++ b/src/com/android/camera/panorama/MosaicRendererSurfaceView.java
@@ -16,7 +16,9 @@
package com.android.camera.panorama;
+import android.app.Activity;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.os.ConditionVariable;
@@ -33,25 +35,36 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
private static final boolean DEBUG = false;
private MosaicRendererSurfaceViewRenderer mRenderer;
private ConditionVariable mPreviewFrameReadyForProcessing;
+ private boolean mIsLandscapeOrientation = true;
public MosaicRendererSurfaceView(Context context) {
super(context);
- init(false, 0, 0);
- setZOrderMediaOverlay(true);
+ initialize(context, false, 0, 0);
}
public MosaicRendererSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
- init(false, 0, 0);
- setZOrderMediaOverlay(true);
+ initialize(context, false, 0, 0);
}
- public MosaicRendererSurfaceView(Context context, boolean translucent, int depth, int stencil) {
+ public MosaicRendererSurfaceView(Context context, boolean translucent,
+ int depth, int stencil) {
super(context);
+ initialize(context, translucent, depth, stencil);
+ }
+
+ private void initialize(Context context, boolean translucent, int depth, int stencil) {
+ getDisplayOrientation(context);
init(translucent, depth, stencil);
setZOrderMediaOverlay(true);
}
+ private void getDisplayOrientation(Context context) {
+ Activity activity = (PanoramaActivity) context;
+ mIsLandscapeOrientation = (activity.getRequestedOrientation()
+ == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE );
+ }
+
private void init(boolean translucent, int depth, int stencil) {
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
@@ -78,7 +91,7 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
new ConfigChooser(5, 6, 5, 0, depth, stencil));
/* Set the renderer responsible for frame rendering */
- mRenderer = new MosaicRendererSurfaceViewRenderer();
+ mRenderer = new MosaicRendererSurfaceViewRenderer(mIsLandscapeOrientation);
setRenderer(mRenderer);
setRenderMode(RENDERMODE_WHEN_DIRTY);
mPreviewFrameReadyForProcessing = new ConditionVariable();
diff --git a/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java b/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java
index b2b2f56..3089972 100755
--- a/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java
+++ b/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java
@@ -25,9 +25,14 @@ import javax.microedition.khronos.opengles.GL10;
public class MosaicRendererSurfaceViewRenderer implements GLSurfaceView.Renderer
{
private static final String TAG = "MosaicRendererSurfaceViewRenderer";
+ private boolean mIsLandscapeOrientation;
private MosaicSurfaceCreateListener mSurfaceCreateListener;
+ public MosaicRendererSurfaceViewRenderer(boolean isLandscapeOrientation) {
+ mIsLandscapeOrientation = isLandscapeOrientation;
+ }
+
/** A callback to be called when the surface is created */
public interface MosaicSurfaceCreateListener {
public void onMosaicSurfaceCreated(final int surface);
@@ -41,7 +46,7 @@ public class MosaicRendererSurfaceViewRenderer implements GLSurfaceView.Renderer
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
- MosaicRenderer.reset(width, height);
+ MosaicRenderer.reset(width, height, mIsLandscapeOrientation);
Log.i(TAG, "Renderer: onSurfaceChanged");
if (mSurfaceCreateListener != null) {
mSurfaceCreateListener.onMosaicSurfaceChanged();
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index 7a7cf78..a65d263 100755
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -25,20 +25,21 @@ import com.android.camera.MenuHelper;
import com.android.camera.ModePicker;
import com.android.camera.OnClickAttr;
import com.android.camera.R;
+import com.android.camera.RotateDialogController;
import com.android.camera.ShutterButton;
import com.android.camera.SoundPlayer;
import com.android.camera.Storage;
import com.android.camera.Thumbnail;
import com.android.camera.Util;
+import com.android.camera.ui.Rotatable;
import com.android.camera.ui.RotateImageView;
+import com.android.camera.ui.RotateLayout;
import com.android.camera.ui.SharePopup;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.res.AssetFileDescriptor;
+import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -47,7 +48,6 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
-import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.hardware.Sensor;
@@ -63,13 +63,13 @@ import android.view.Gravity;
import android.view.Menu;
import android.view.OrientationEventListener;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
import java.io.File;
import java.util.List;
@@ -88,6 +88,9 @@ public class PanoramaActivity extends ActivityBase implements
private static final int MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL = 2;
private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 3;
private static final int MSG_RESET_TO_PREVIEW = 4;
+ private static final int MSG_CLEAR_SCREEN_DELAY = 5;
+
+ private static final int SCREEN_DELAY = 2 * 60 * 1000;
private static final String TAG = "PanoramaActivity";
private static final int PREVIEW_STOPPED = 0;
@@ -109,7 +112,7 @@ public class PanoramaActivity extends ActivityBase implements
private View mCaptureLayout;
private View mReviewLayout;
private ImageView mReview;
- private TextView mCaptureIndicator;
+ private RotateLayout mCaptureIndicator;
private PanoProgressBar mPanoProgressBar;
private PanoProgressBar mSavingProgressBar;
private View mFastIndicationBorder;
@@ -121,10 +124,9 @@ public class PanoramaActivity extends ActivityBase implements
private Object mWaitObject = new Object();
private String mPreparePreviewString;
- private AlertDialog mAlertDialog;
- private ProgressDialog mProgressDialog;
private String mDialogTitle;
- private String mDialogOk;
+ private String mDialogOkString;
+ private String mDialogPanoramaFailedString;
private int mIndicatorColor;
private int mIndicatorColorFast;
@@ -177,6 +179,8 @@ public class PanoramaActivity extends ActivityBase implements
private int mDeviceOrientation;
private int mOrientationCompensation;
+ private RotateDialogController mRotateDialog;
+
private class MosaicJpeg {
public MosaicJpeg(byte[] data, int width, int height) {
this.data = data;
@@ -251,8 +255,6 @@ public class PanoramaActivity extends ActivityBase implements
super.onCreate(icicle);
Window window = getWindow();
- window.setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Util.enterLightsOutMode(window);
Util.initializeScreenBrightness(window, getContentResolver());
@@ -271,7 +273,9 @@ public class PanoramaActivity extends ActivityBase implements
mPreparePreviewString =
getResources().getString(R.string.pano_dialog_prepare_preview);
mDialogTitle = getResources().getString(R.string.pano_dialog_title);
- mDialogOk = getResources().getString(R.string.dialog_ok);
+ mDialogOkString = getResources().getString(R.string.dialog_ok);
+ mDialogPanoramaFailedString =
+ getResources().getString(R.string.pano_dialog_panorama_failed);
mMainHandler = new Handler() {
@Override
@@ -297,36 +301,28 @@ public class PanoramaActivity extends ActivityBase implements
if (mPausing) {
resetToPreview();
} else {
- mAlertDialog.show();
+ mRotateDialog.showAlertDialog(
+ mDialogTitle, mDialogPanoramaFailedString,
+ mDialogOkString, new Runnable() {
+ @Override
+ public void run() {
+ resetToPreview();
+ }},
+ null, null);
}
break;
case MSG_RESET_TO_PREVIEW:
onBackgroundThreadFinished();
resetToPreview();
+ break;
+ case MSG_CLEAR_SCREEN_DELAY:
+ getWindow().clearFlags(WindowManager.LayoutParams.
+ FLAG_KEEP_SCREEN_ON);
+ break;
}
clearMosaicFrameProcessorIfNeeded();
}
};
-
- mAlertDialog = (new AlertDialog.Builder(this))
- .setTitle(mDialogTitle)
- .setMessage(R.string.pano_dialog_panorama_failed)
- .create();
- mAlertDialog.setCancelable(false);
- mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE, mDialogOk,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- resetToPreview();
- }
- });
- }
-
- @Override
- public void onStart() {
- super.onStart();
- updateThumbnailButton();
}
private void setupCamera() {
@@ -577,6 +573,7 @@ public class PanoramaActivity extends ActivityBase implements
mPanoProgressBar.setIndicatorWidth(20);
mPanoProgressBar.setMaxProgress(DEFAULT_SWEEP_ANGLE);
mPanoProgressBar.setVisibility(View.VISIBLE);
+ keepScreenOn();
}
private void stopCapture(boolean aborted) {
@@ -592,7 +589,7 @@ public class PanoramaActivity extends ActivityBase implements
mSurfaceTexture.setOnFrameAvailableListener(null);
if (!aborted && !mThreadRunning) {
- showDialog(mPreparePreviewString);
+ mRotateDialog.showWaitingDialog(mPreparePreviewString);
runBackgroundThread(new Thread() {
@Override
public void run() {
@@ -612,6 +609,7 @@ public class PanoramaActivity extends ActivityBase implements
}
// do we have to wait for the thread to complete before enabling this?
if (mModePicker != null) mModePicker.setEnabled(true);
+ keepScreenOnAwhile();
}
private void showTooFastIndication() {
@@ -682,7 +680,7 @@ public class PanoramaActivity extends ActivityBase implements
mSavingProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
mSavingProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_indication));
- mCaptureIndicator = (TextView) findViewById(R.id.pano_capture_indicator);
+ mCaptureIndicator = (RotateLayout) findViewById(R.id.pano_capture_indicator);
mThumbnailView = (RotateImageView) findViewById(R.id.thumbnail);
mThumbnailView.enableFilter(false);
@@ -702,6 +700,24 @@ public class PanoramaActivity extends ActivityBase implements
mShutterButton.setOnShutterButtonListener(this);
mPanoLayout = findViewById(R.id.pano_layout);
+
+ mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog);
+
+ if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ Rotatable[] rotateLayout = {
+ (Rotatable) findViewById(R.id.pano_pan_progress_bar_layout),
+ (Rotatable) findViewById(R.id.pano_capture_too_fast_textview_layout),
+ (Rotatable) findViewById(R.id.pano_review_saving_indication_layout),
+ (Rotatable) findViewById(R.id.pano_saving_progress_bar_layout),
+ (Rotatable) findViewById(R.id.pano_review_cancel_button_layout),
+ (Rotatable) mRotateDialog,
+ (Rotatable) mCaptureIndicator,
+ (Rotatable) mModePicker,
+ (Rotatable) mThumbnailView};
+ for (Rotatable r : rotateLayout) {
+ r.setOrientation(270);
+ }
+ }
}
@Override
@@ -755,6 +771,14 @@ public class PanoramaActivity extends ActivityBase implements
t.start();
}
+ private void initThumbnailButton() {
+ // Load the thumbnail from the disk.
+ if (mThumbnail == null) {
+ mThumbnail = Thumbnail.loadFrom(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME));
+ }
+ updateThumbnailButton();
+ }
+
private void updateThumbnailButton() {
// Update last image if URI is invalid and the storage is ready.
ContentResolver contentResolver = getContentResolver();
@@ -801,12 +825,6 @@ public class PanoramaActivity extends ActivityBase implements
reportProgress();
}
- private void showDialog(String str) {
- mProgressDialog = new ProgressDialog(this);
- mProgressDialog.setMessage(str);
- mProgressDialog.show();
- }
-
private void runBackgroundThread(Thread thread) {
mThreadRunning = true;
thread.start();
@@ -814,10 +832,7 @@ public class PanoramaActivity extends ActivityBase implements
private void onBackgroundThreadFinished() {
mThreadRunning = false;
- if (mProgressDialog != null) {
- mProgressDialog.dismiss();
- mProgressDialog = null;
- }
+ mRotateDialog.dismissDialog();
}
private void cancelHighResComputation() {
@@ -951,6 +966,7 @@ public class PanoramaActivity extends ActivityBase implements
mMosaicView.onPause();
clearMosaicFrameProcessorIfNeeded();
mOrientationEventListener.disable();
+ resetScreenOn();
System.gc();
}
@@ -968,11 +984,25 @@ public class PanoramaActivity extends ActivityBase implements
// has to be decided by camera device.
initMosaicFrameProcessorIfNeeded();
mMosaicView.onResume();
+
+ initThumbnailButton();
+ keepScreenOnAwhile();
}
+ /**
+ * Generate the final mosaic image.
+ *
+ * @param highRes flag to indicate whether we want to get a high-res version.
+ * @return a MosaicJpeg with its isValid flag set to true if successful; null if the generation
+ * process is cancelled; and a MosaicJpeg with its isValid flag set to false if there
+ * is an error in generating the final mosaic.
+ */
public MosaicJpeg generateFinalMosaic(boolean highRes) {
- if (mMosaicFrameProcessor.createMosaic(highRes) == Mosaic.MOSAIC_RET_CANCELLED) {
+ int mosaicReturnCode = mMosaicFrameProcessor.createMosaic(highRes);
+ if (mosaicReturnCode == Mosaic.MOSAIC_RET_CANCELLED) {
return null;
+ } else if (mosaicReturnCode == Mosaic.MOSAIC_RET_ERROR) {
+ return new MosaicJpeg();
}
byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21();
@@ -1021,9 +1051,10 @@ public class PanoramaActivity extends ActivityBase implements
// the screen).
if (mCameraState != PREVIEW_STOPPED) stopCameraPreview();
- int orientation = Util.getDisplayOrientation(Util.getDisplayRotation(this),
- CameraHolder.instance().getBackCameraId());
- mCameraDevice.setDisplayOrientation(orientation);
+ // Set the display orientation to 0, so that the underlying mosaic library
+ // can always get undistorted mPreviewWidth x mPreviewHeight image data
+ // from SurfaceTexture.
+ mCameraDevice.setDisplayOrientation(0);
setPreviewTexture(mSurfaceTexture);
@@ -1044,4 +1075,26 @@ public class PanoramaActivity extends ActivityBase implements
}
mCameraState = PREVIEW_STOPPED;
}
+
+ @Override
+ public void onUserInteraction() {
+ super.onUserInteraction();
+ if (mCaptureState != CAPTURE_STATE_MOSAIC) keepScreenOnAwhile();
+ }
+
+ private void resetScreenOn() {
+ mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY);
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+
+ private void keepScreenOnAwhile() {
+ mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ mMainHandler.sendEmptyMessageDelayed(MSG_CLEAR_SCREEN_DELAY, SCREEN_DELAY);
+ }
+
+ private void keepScreenOn() {
+ mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
}
diff --git a/src/com/android/camera/ui/AbstractIndicatorButton.java b/src/com/android/camera/ui/AbstractIndicatorButton.java
index a661586..0ff7b19 100644
--- a/src/com/android/camera/ui/AbstractIndicatorButton.java
+++ b/src/com/android/camera/ui/AbstractIndicatorButton.java
@@ -106,10 +106,10 @@ public abstract class AbstractIndicatorButton extends RotateImageView implements
}
@Override
- public void setDegree(int degree) {
- super.setDegree(degree);
+ public void setOrientation(int orientation) {
+ super.setOrientation(orientation);
if (mPopup != null) {
- mPopup.setOrientation(degree);
+ mPopup.setOrientation(orientation);
}
}
diff --git a/src/com/android/camera/ui/ControlPanelLayout.java b/src/com/android/camera/ui/ControlPanelLayout.java
index f85d955..24efb8b 100644
--- a/src/com/android/camera/ui/ControlPanelLayout.java
+++ b/src/com/android/camera/ui/ControlPanelLayout.java
@@ -16,7 +16,9 @@
package com.android.camera.ui;
+import android.app.Activity;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RelativeLayout;
@@ -25,8 +27,7 @@ import android.widget.RelativeLayout;
* A layout which handles the the width of the control panel, which contains
* the shutter button, thumbnail, front/back camera picker, and mode picker.
* The purpose of this is to have a consistent width of control panel in camera,
- * camcorder, and panorama modes. The control panel can also be GONE and the
- * preview can expand to full-screen in panorama.
+ * camcorder, and panorama modes.
*/
public class ControlPanelLayout extends RelativeLayout {
private static final String TAG = "ControlPanelLayout";
@@ -39,29 +40,43 @@ public class ControlPanelLayout extends RelativeLayout {
protected void onMeasure(int widthSpec, int heightSpec) {
int widthSpecSize = MeasureSpec.getSize(widthSpec);
int heightSpecSize = MeasureSpec.getSize(heightSpec);
- int widthMode = MeasureSpec.getMode(widthSpec);
- int measuredWidth = 0;
+ int measuredSize = 0;
+ int mode, longSideSize, shortSideSize, specSize;
- if (widthSpecSize > 0 && heightSpecSize > 0 && widthMode == MeasureSpec.AT_MOST) {
+ boolean isLandscape = (((Activity) getContext()).getRequestedOrientation()
+ == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+
+ if (isLandscape) {
+ mode = MeasureSpec.getMode(widthSpec);
+ longSideSize = widthSpecSize;
+ shortSideSize = heightSpecSize;
+ specSize = widthSpecSize;
+ } else {
+ mode = MeasureSpec.getMode(heightSpec);
+ longSideSize = heightSpecSize;
+ shortSideSize = widthSpecSize;
+ specSize = heightSpecSize;
+ }
+
+ if (widthSpecSize > 0 && heightSpecSize > 0 && mode == MeasureSpec.AT_MOST) {
// Calculate how big 4:3 preview occupies. Then deduct it from the
// width of the parent.
- measuredWidth = (int) (widthSpecSize - heightSpecSize / 3.0 * 4.0 - 16);
+ measuredSize = (int) (longSideSize - shortSideSize / 3.0 * 4.0);
} else {
- Log.e(TAG, "layout_width of ControlPanelLayout should be wrap_content");
+ Log.e(TAG, "layout_xxx of ControlPanelLayout should be wrap_content");
}
- // Make sure the width is bigger than the minimum width.
- int minWidth = getSuggestedMinimumWidth();
- if (minWidth > measuredWidth) {
- measuredWidth = minWidth;
+ // The width cannot be bigger than the constraint.
+ if (mode == MeasureSpec.AT_MOST && measuredSize > specSize) {
+ measuredSize = specSize;
}
- // The width cannot be bigger than the constraint.
- if (widthMode == MeasureSpec.AT_MOST && measuredWidth > widthSpecSize) {
- measuredWidth = widthSpecSize;
+ if (isLandscape) {
+ widthSpec = MeasureSpec.makeMeasureSpec(measuredSize, MeasureSpec.EXACTLY);
+ } else {
+ heightSpec = MeasureSpec.makeMeasureSpec(measuredSize, MeasureSpec.EXACTLY);
}
- super.onMeasure(MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY),
- heightSpec);
+ super.onMeasure(widthSpec, heightSpec);
}
}
diff --git a/src/com/android/camera/ui/EffectSettingPopup.java b/src/com/android/camera/ui/EffectSettingPopup.java
index c4a4d49..a0f9be0 100644
--- a/src/com/android/camera/ui/EffectSettingPopup.java
+++ b/src/com/android/camera/ui/EffectSettingPopup.java
@@ -180,11 +180,19 @@ public class EffectSettingPopup extends AbstractSettingPopup implements
@Override
public void onItemClick(AdapterView<?> parent, View view,
int index, long id) {
+ String value;
if (parent == mSillyFacesGrid) {
- String value = (String) mSillyFacesItem.get(index).get("value");
- mPreference.setValue(value);
+ value = (String) mSillyFacesItem.get(index).get("value");
} else if (parent == mBackgroundGrid) {
- String value = (String) mBackgroundItem.get(index).get("value");
+ value = (String) mBackgroundItem.get(index).get("value");
+ } else {
+ return;
+ }
+
+ // Tapping the selected effect will deselect it (clear effects).
+ if (value.equals(mPreference.getValue())) {
+ mPreference.setValue(mNoEffect);
+ } else {
mPreference.setValue(value);
}
reloadPreference();
diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java
index 9018886..ed59682 100644
--- a/src/com/android/camera/ui/FaceView.java
+++ b/src/com/android/camera/ui/FaceView.java
@@ -29,7 +29,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
-public class FaceView extends View implements FocusIndicator {
+public class FaceView extends View implements FocusIndicator, Rotatable {
private final String TAG = "FaceView";
private final boolean LOGV = false;
// The value for android.hardware.Camera.setDisplayOrientation.
diff --git a/src/com/android/camera/ui/IndicatorControl.java b/src/com/android/camera/ui/IndicatorControl.java
index 86b0cc9..cac38b8 100644
--- a/src/com/android/camera/ui/IndicatorControl.java
+++ b/src/com/android/camera/ui/IndicatorControl.java
@@ -35,7 +35,7 @@ import java.util.ArrayList;
* A view that contains camera setting indicators.
*/
public abstract class IndicatorControl extends RelativeLayout implements
- IndicatorButton.Listener, OtherSettingsPopup.Listener {
+ IndicatorButton.Listener, OtherSettingsPopup.Listener, Rotatable {
private static final String TAG = "IndicatorControl";
public static final int MODE_CAMERA = 0;
public static final int MODE_VIDEO = 1;
@@ -45,7 +45,7 @@ public abstract class IndicatorControl extends RelativeLayout implements
protected CameraPicker mCameraPicker;
private PreferenceGroup mPreferenceGroup;
- private int mDegree = 0;
+ private int mOrientation = 0;
protected int mCurrentMode = MODE_CAMERA;
@@ -61,15 +61,13 @@ public abstract class IndicatorControl extends RelativeLayout implements
super(context, attrs);
}
- public void setDegree(int degree) {
- mDegree = degree;
+ public void setOrientation(int orientation) {
+ mOrientation = orientation;
int count = getChildCount();
for (int i = 0 ; i < count ; ++i) {
View view = getChildAt(i);
- if (view instanceof RotateImageView) {
- ((RotateImageView) view).setDegree(degree);
- } else if (view instanceof ZoomControl) {
- ((ZoomControl) view).setDegree(degree);
+ if (view instanceof Rotatable) {
+ ((Rotatable) view).setOrientation(orientation);
}
}
}
diff --git a/src/com/android/camera/ui/IndicatorControlBar.java b/src/com/android/camera/ui/IndicatorControlBar.java
index 6c2151d..8ab61fd 100644
--- a/src/com/android/camera/ui/IndicatorControlBar.java
+++ b/src/com/android/camera/ui/IndicatorControlBar.java
@@ -87,20 +87,19 @@ public class IndicatorControlBar extends IndicatorControl implements
int count = getChildCount();
if (count == 0) return;
- int width = right - left;
+ int height = bottom - top;
- // First indicator will be CameraPicker if exists.
- if (mCameraPicker != null) {
- mCameraPicker.layout(0, padding, width, padding + width);
- }
+ mSecondLevelIcon.layout(0, 0, height, height);
// Layout the zoom control if required.
- int offset = padding + width; // the padding and the icon height
+ int offset = padding + height; // the padding and the icon height
if (mZoomControl != null) {
- mZoomControl.layout(0, offset, width, bottom - top - offset);
+ mZoomControl.layout(offset, 0, right - left - offset, height);
}
- mSecondLevelIcon.layout(0, bottom - top - offset, width, bottom - top);
+ if (mCameraPicker != null) {
+ mCameraPicker.layout(right - left - offset, 0, right - left, height);
+ }
}
@Override
diff --git a/src/com/android/camera/ui/IndicatorControlBarContainer.java b/src/com/android/camera/ui/IndicatorControlBarContainer.java
index 6b60ace..3c907a8 100644
--- a/src/com/android/camera/ui/IndicatorControlBarContainer.java
+++ b/src/com/android/camera/ui/IndicatorControlBarContainer.java
@@ -43,14 +43,14 @@ public class IndicatorControlBarContainer extends IndicatorControlContainer {
public IndicatorControlBarContainer(Context context, AttributeSet attrs) {
super(context, attrs);
mFadeIn = AnimationUtils.loadAnimation(
- context, R.anim.grow_fade_in_from_top);
+ context, R.anim.first_level_fade_in);
mFadeOut = AnimationUtils.loadAnimation(
- context, R.anim.shrink_fade_out_from_bottom);
+ context, R.anim.first_level_fade_out);
mFadeOut.setAnimationListener(mAnimationListener);
mSecondLevelFadeIn = AnimationUtils.loadAnimation(
- context, R.anim.grow_fade_in_from_bottom);
+ context, R.anim.second_level_fade_in);
mSecondLevelFadeOut = AnimationUtils.loadAnimation(
- context, R.anim.shrink_fade_out_from_top);
+ context, R.anim.second_level_fade_out);
mSecondLevelFadeOut.setAnimationListener(mAnimationListener);
}
@@ -75,9 +75,9 @@ public class IndicatorControlBarContainer extends IndicatorControlContainer {
secondLevelKeys, secondLevelOtherSettingKeys);
}
- public void setDegree(int degree) {
- mIndicatorControlBar.setDegree(degree);
- mSecondLevelIndicatorControlBar.setDegree(degree);
+ public void setOrientation(int orientation) {
+ mIndicatorControlBar.setOrientation(orientation);
+ mSecondLevelIndicatorControlBar.setOrientation(orientation);
}
@Override
diff --git a/src/com/android/camera/ui/IndicatorControlWheel.java b/src/com/android/camera/ui/IndicatorControlWheel.java
index af36e11..3b8bea4 100644
--- a/src/com/android/camera/ui/IndicatorControlWheel.java
+++ b/src/com/android/camera/ui/IndicatorControlWheel.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.RectF;
import android.os.Handler;
import android.os.SystemClock;
@@ -65,6 +66,7 @@ public class IndicatorControlWheel extends IndicatorControl implements
private static final int TIME_LAPSE_ARC_WIDTH = 6;
private final int HIGHLIGHT_COLOR;
+ private final int HIGHLIGHT_FAN_COLOR;
private final int TIME_LAPSE_ARC_COLOR;
// The center of the shutter button.
@@ -115,6 +117,7 @@ public class IndicatorControlWheel extends IndicatorControl implements
super(context, attrs);
Resources resources = context.getResources();
HIGHLIGHT_COLOR = resources.getColor(R.color.review_control_pressed_color);
+ HIGHLIGHT_FAN_COLOR = resources.getColor(R.color.review_control_pressed_fan_color);
TIME_LAPSE_ARC_COLOR = resources.getColor(R.color.time_lapse_arc);
setWillNotDraw(false);
@@ -135,9 +138,7 @@ public class IndicatorControlWheel extends IndicatorControl implements
}
}
- @Override
- public void onClick(View view) {
- if (view == mZoomIcon) return;
+ private void changeIndicatorsLevel() {
mPressedIndex = -1;
dismissSettingPopup();
mInAnimation = true;
@@ -145,6 +146,12 @@ public class IndicatorControlWheel extends IndicatorControl implements
requestLayout();
}
+ @Override
+ public void onClick(View view) {
+ if (view == mZoomIcon) return;
+ changeIndicatorsLevel();
+ }
+
public void initialize(Context context, PreferenceGroup group,
boolean isZoomSupported, String[] keys, String[] otherSettingKeys) {
mShutterButtonRadius = IndicatorControlWheelContainer.SHUTTER_BUTTON_RADIUS;
@@ -291,7 +298,6 @@ public class IndicatorControlWheel extends IndicatorControl implements
double increment = Math.toRadians(expectedAngle)
- mChildRadians[mSecondLevelStartIndex];
for (int i = 0 ; i < getChildCount(); ++i) mChildRadians[i] += increment;
- requestLayout();
}
@Override
@@ -309,7 +315,7 @@ public class IndicatorControlWheel extends IndicatorControl implements
// The icons are spreaded on the left side of the shutter button.
for (int i = 0; i < getChildCount(); ++i) {
View view = getChildAt(i);
- if (!view.isEnabled()) continue;
+ // We still need to show the disabled indicators in the second level.
double radian = mChildRadians[i];
double startVisibleRadians = mInAnimation
? mStartVisibleRadians[1]
@@ -317,8 +323,9 @@ public class IndicatorControlWheel extends IndicatorControl implements
double endVisibleRadians = mInAnimation
? mEndVisibleRadians[1]
: mEndVisibleRadians[mCurrentLevel];
- if ((radian < (startVisibleRadians - HIGHLIGHT_RADIANS / 2)) ||
- (radian > (endVisibleRadians + HIGHLIGHT_RADIANS / 2))) {
+ if ((!view.isEnabled() && (mCurrentLevel == 0))
+ || (radian < (startVisibleRadians - HIGHLIGHT_RADIANS / 2))
+ || (radian > (endVisibleRadians + HIGHLIGHT_RADIANS / 2))) {
view.setVisibility(View.GONE);
continue;
}
@@ -415,19 +422,35 @@ public class IndicatorControlWheel extends IndicatorControl implements
@Override
protected void onDraw(Canvas canvas) {
- // Draw highlight.
- float delta = mStrokeWidth * 0.5f;
- float radius = (float) (mWheelRadius + mStrokeWidth * 0.5 + EDGE_STROKE_WIDTH);
- mBackgroundRect.set(mCenterX - radius, mCenterY - radius, mCenterX + radius,
- mCenterY + radius);
-
int selectedIndex = getSelectedIndicatorIndex();
// Draw the highlight arc if an indicator is selected or being pressed.
- if (selectedIndex >= 0) {
+ if (selectedIndex >= 0) {
int degree = (int) Math.toDegrees(mChildRadians[selectedIndex]);
+ float innerR = (float) mShutterButtonRadius;
+ float outerR = (float) (mShutterButtonRadius + mStrokeWidth +
+ EDGE_STROKE_WIDTH * 0.5);
+
+ // Construct the path of the fan-shaped semi-transparent area.
+ Path fanPath = new Path();
+ mBackgroundRect.set(mCenterX - innerR, mCenterY - innerR,
+ mCenterX + innerR, mCenterY + innerR);
+ fanPath.arcTo(mBackgroundRect, -degree + HIGHLIGHT_DEGREES / 2,
+ -HIGHLIGHT_DEGREES);
+ mBackgroundRect.set(mCenterX - outerR, mCenterY - outerR,
+ mCenterX + outerR, mCenterY + outerR);
+ fanPath.arcTo(mBackgroundRect, -degree - HIGHLIGHT_DEGREES / 2,
+ HIGHLIGHT_DEGREES);
+ fanPath.close();
+
mBackgroundPaint.setStrokeWidth(HIGHLIGHT_WIDTH);
- mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND);
+ mBackgroundPaint.setStrokeCap(Paint.Cap.SQUARE);
+ mBackgroundPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ mBackgroundPaint.setColor(HIGHLIGHT_FAN_COLOR);
+ canvas.drawPath(fanPath, mBackgroundPaint);
+
+ // Draw the highlight edge
+ mBackgroundPaint.setStyle(Paint.Style.STROKE);
mBackgroundPaint.setColor(HIGHLIGHT_COLOR);
canvas.drawArc(mBackgroundRect, -degree - HIGHLIGHT_DEGREES / 2,
HIGHLIGHT_DEGREES, false, mBackgroundPaint);
@@ -492,4 +515,10 @@ public class IndicatorControlWheel extends IndicatorControl implements
invalidate();
}
}
+
+ public void dismissSecondLevelIndicator() {
+ if (mCurrentLevel == 1) {
+ changeIndicatorsLevel();
+ }
+ }
}
diff --git a/src/com/android/camera/ui/IndicatorControlWheelContainer.java b/src/com/android/camera/ui/IndicatorControlWheelContainer.java
index 14539da..a10136b 100644
--- a/src/com/android/camera/ui/IndicatorControlWheelContainer.java
+++ b/src/com/android/camera/ui/IndicatorControlWheelContainer.java
@@ -191,9 +191,9 @@ public class IndicatorControlWheelContainer extends IndicatorControlContainer {
}
@Override
- public void setDegree(int degree) {
- mIndicatorControlWheel.setDegree(degree);
- mZoomControlWheel.setDegree(degree);
+ public void setOrientation(int orientation) {
+ mIndicatorControlWheel.setOrientation(orientation);
+ mZoomControlWheel.setOrientation(orientation);
}
public void startTimeLapseAnimation(int timeLapseInterval, long startTime) {
@@ -223,6 +223,6 @@ public class IndicatorControlWheelContainer extends IndicatorControlContainer {
@Override
public void dismissSecondLevelIndicator() {
- // TODO: back to first-level indicator set.
+ mIndicatorControlWheel.dismissSecondLevelIndicator();
}
}
diff --git a/src/com/android/camera/ui/OneRowGridView.java b/src/com/android/camera/ui/OneRowGridView.java
new file mode 100644
index 0000000..5e37d35
--- /dev/null
+++ b/src/com/android/camera/ui/OneRowGridView.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 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 com.android.camera.R;
+import com.android.camera.Util;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridView;
+
+public class OneRowGridView extends GridView {
+ public OneRowGridView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Once we know the number of children in this view, we have to set
+ // the correct width and height for containing the icons in one row.
+ int n = getChildCount();
+ if (n == 0) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ } else {
+ setMeasuredDimension((n * getChildAt(0).getMeasuredWidth()),
+ getMeasuredHeight());
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/RightAlignedHorizontalScrollView.java b/src/com/android/camera/ui/RightAlignedHorizontalScrollView.java
new file mode 100644
index 0000000..cd4c5f5
--- /dev/null
+++ b/src/com/android/camera/ui/RightAlignedHorizontalScrollView.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 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.view.View;
+import android.util.AttributeSet;
+import android.widget.HorizontalScrollView;
+
+public class RightAlignedHorizontalScrollView extends HorizontalScrollView {
+
+ public RightAlignedHorizontalScrollView(Context context) {
+ super(context);
+ }
+
+ public RightAlignedHorizontalScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (changed) {
+ // Get the width of the child, i.e. the LinearLayout, and scroll to
+ // the rightmost position.
+ View child = getChildAt(0);
+ if (child != null) scrollTo(child.getWidth(), 0);
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/RotateImageView.java b/src/com/android/camera/ui/RotateImageView.java
index 390d705..f47a26b 100644
--- a/src/com/android/camera/ui/RotateImageView.java
+++ b/src/com/android/camera/ui/RotateImageView.java
@@ -16,8 +16,6 @@
package com.android.camera.ui;
-import com.android.camera.ui.Rotatable;
-
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -66,12 +64,8 @@ public class RotateImageView extends ColorFilterImageView implements Rotatable {
return mTargetDegree;
}
- public void setOrientation(int orientation) {
- setDegree(orientation);
- }
-
// Rotate the view counter-clockwise
- public void setDegree(int degree) {
+ public void setOrientation(int degree) {
// make sure in the range of [0, 359]
degree = degree >= 0 ? degree % 360 : degree % 360 + 360;
if (degree == mTargetDegree) return;
diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java
index 24815f8..e66e71a 100644
--- a/src/com/android/camera/ui/RotateLayout.java
+++ b/src/com/android/camera/ui/RotateLayout.java
@@ -16,8 +16,6 @@
package com.android.camera.ui;
-import com.android.camera.ui.Rotatable;
-
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
diff --git a/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java b/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java
index c9037d9..1fb9a80 100644
--- a/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java
+++ b/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java
@@ -39,7 +39,7 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
private View mDivider; // the divider line
private View mIndicatorHighlight; // the side highlight bar
private View mPopupedIndicator;
- int mDegree = 0;
+ int mOrientation = 0;
int mSelectedIndex = -1;
// There are some views in the ViewGroup before adding the indicator buttons,
// such as Close icon, divider line and the hightlight bar, we need to
@@ -64,7 +64,7 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
setPreferenceGroup(group);
mNonIndicatorButtonCount = getChildCount();
addControls(keys, otherSettingKeys);
- if (mDegree != 0) setDegree(mDegree);
+ if (mOrientation != 0) setOrientation(mOrientation);
}
public void onClick(View view) {
@@ -73,20 +73,20 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
OnIndicatorEventListener.EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR);
}
- private int getTouchViewIndex(int y, int height) {
+ private int getTouchViewIndex(int x, int width) {
// If the current touch location is on close icon and above.
- if (y < mCloseIcon.getBottom()) return indexOfChild(mCloseIcon);
+ if (x > mCloseIcon.getLeft()) return indexOfChild(mCloseIcon);
// Calculate if the touch event is on the indicator buttons.
int count = getChildCount();
if (count == mNonIndicatorButtonCount) return -1;
// The baseline will be the first indicator button's top minus spacing.
View firstIndicatorButton = getChildAt(mNonIndicatorButtonCount);
- int baselineY = firstIndicatorButton.getTop() - (ICON_SPACING / 2);
- if (y < baselineY) return -1;
- int iconHeight = firstIndicatorButton.getMeasuredHeight();
- int buttonRange = iconHeight + ICON_SPACING;
- return (mNonIndicatorButtonCount + (y - baselineY) / buttonRange);
+ int baselineX = firstIndicatorButton.getRight() + (ICON_SPACING / 2);
+ if (x > baselineX) return -1;
+ int iconWidth = firstIndicatorButton.getMeasuredWidth();
+ int buttonRange = iconWidth + ICON_SPACING;
+ return (mNonIndicatorButtonCount + ((baselineX - x) / buttonRange));
}
@Override
@@ -98,12 +98,12 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
double x = (double) event.getX();
double y = (double) event.getY();
- int height = getHeight();
- if (height == 0) return false; // the event is sent before onMeasure()
- if (x > getWidth()) x = getWidth();
- if (y >= height) y = height - 1;
+ int width = getWidth();
+ if (width == 0) return false; // the event is sent before onMeasure()
+ if (x > width) x = width;
+ if (y >= getHeight()) y = getHeight() - 1;
- int index = getTouchViewIndex((int) y, height);
+ int index = getTouchViewIndex((int) x, width);
if (index == -1) return true;
View b = getChildAt(index);
b.dispatchTouchEvent(event);
@@ -151,9 +151,9 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
}
@Override
- public void setDegree(int degree) {
- mDegree = degree;
- super.setDegree(degree);
+ public void setOrientation(int orientation) {
+ mOrientation = orientation;
+ super.setOrientation(orientation);
}
@Override
@@ -163,26 +163,26 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
if (count == 0) return;
int width = right - left;
int height = bottom - top;
- int iconHeight = mCloseIcon.getMeasuredHeight();
- int padding = getPaddingTop();
-
- // The first icon is close button.
- int offsetY = padding;
- mCloseIcon.layout(0, padding, width, (padding + iconHeight));
-
- // And layout the divider line.
- offsetY += (iconHeight + padding);
- mDivider.layout(padding, offsetY,
- (width - padding), (offsetY + mDivider.getMeasuredHeight()));
+ int iconWidth = mCloseIcon.getMeasuredWidth();
+ int padding = getPaddingLeft();
// Layout from the last icon up.
- int startY = height - iconHeight - padding;
- int decrement = iconHeight + ICON_SPACING;
+ int offsetX = padding;
+ int increment = iconWidth + ICON_SPACING;
for (int i = count - 1; i >= mNonIndicatorButtonCount; --i) {
- getChildAt(i).layout(0, startY, width, startY + iconHeight);
- startY -= decrement;
+ getChildAt(i).layout(offsetX, 0, offsetX + iconWidth, height);
+ offsetX += increment;
}
+ // And layout the divider line.
+ offsetX = width - iconWidth - 2 * padding;
+ mDivider.layout(offsetX, padding, (offsetX + mDivider.getMeasuredWidth()),
+ (height - padding));
+
+ offsetX = width - iconWidth - padding;
+ // The first icon is close button.
+ mCloseIcon.layout(offsetX, 0, (offsetX + iconWidth), height);
+
// Hightlight the selected indicator if exists.
if (mPopupedIndicator == null) {
mIndicatorHighlight.setVisibility(View.GONE);
@@ -190,9 +190,9 @@ public class SecondLevelIndicatorControlBar extends IndicatorControl implements
mIndicatorHighlight.setVisibility(View.VISIBLE);
// Keep the top and bottom of the hightlight the same as
// the 'active' indicator button.
- mIndicatorHighlight.layout(0, mPopupedIndicator.getTop(),
- mIndicatorHighlight.getLayoutParams().width,
- mPopupedIndicator.getBottom());
+ mIndicatorHighlight.layout(mPopupedIndicator.getLeft(), 0,
+ mPopupedIndicator.getRight(),
+ mIndicatorHighlight.getLayoutParams().height);
}
}
diff --git a/src/com/android/camera/ui/SharePopup.java b/src/com/android/camera/ui/SharePopup.java
index de78f66..134b7c0 100644
--- a/src/com/android/camera/ui/SharePopup.java
+++ b/src/com/android/camera/ui/SharePopup.java
@@ -23,6 +23,7 @@ import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -38,7 +39,7 @@ import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
-import android.widget.ListView;
+import android.widget.GridView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
@@ -50,7 +51,7 @@ import java.util.Map;
// A popup window that contains a big thumbnail and a list of apps to share.
public class SharePopup extends PopupWindow implements View.OnClickListener,
- View.OnTouchListener, AdapterView.OnItemClickListener {
+ View.OnTouchListener, AdapterView.OnItemClickListener, Rotatable {
private static final String TAG = "SharePopup";
private static final String ADAPTER_COLUMN_ICON = "icon";
private Context mContext;
@@ -65,7 +66,7 @@ public class SharePopup extends PopupWindow implements View.OnClickListener,
// A view that contains a list of application icons and the share view.
private View mRootView;
// The list of the application icons.
- private ListView mShareList;
+ private GridView mShareList;
// A rotated view that contains the thumbnail.
private RotateLayout mThumbnailRotateLayout;
private RotateLayout mGotoGalleryRotate;
@@ -114,8 +115,7 @@ public class SharePopup extends PopupWindow implements View.OnClickListener,
// This is required because popup window is full screen.
sharePopup.setOnTouchListener(this);
mThumbnailRotateLayout = (RotateLayout) sharePopup.findViewById(R.id.thumbnail_rotate_layout);
- mShareList = (ListView) sharePopup.findViewById(R.id.share_list);
- mShareList.setDivider(null);
+ mShareList = (GridView) sharePopup.findViewById(R.id.share_list);
mThumbnail = (ImageView) sharePopup.findViewById(R.id.thumbnail);
mThumbnail.setImageBitmap(bitmap);
mShareView = (ViewGroup) sharePopup.findViewById(R.id.share_view);
@@ -279,10 +279,19 @@ public class SharePopup extends PopupWindow implements View.OnClickListener,
items.add(map);
mComponent.add(component);
}
+
+ // On phone UI, we have to know how many icons in the grid view before
+ // the view is measured.
+ if (((Activity) mContext).getRequestedOrientation()
+ == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ mShareList.setNumColumns(items.size());
+ }
+
SimpleAdapter listItemAdapter = new MySimpleAdapter(mContext, items,
R.layout.share_icon,
new String[] {ADAPTER_COLUMN_ICON},
new int[] {R.id.icon});
+
listItemAdapter.setViewBinder(mViewBinder);
mShareList.setAdapter(listItemAdapter);
mShareList.setOnItemClickListener(this);
diff --git a/src/com/android/camera/ui/ZoomControl.java b/src/com/android/camera/ui/ZoomControl.java
index 1809d18..f2971cd 100644
--- a/src/com/android/camera/ui/ZoomControl.java
+++ b/src/com/android/camera/ui/ZoomControl.java
@@ -29,7 +29,7 @@ import android.widget.RelativeLayout;
* A view that contains camera zoom control which could adjust the zoom in/out
* if the camera supports zooming.
*/
-public abstract class ZoomControl extends RelativeLayout {
+public abstract class ZoomControl extends RelativeLayout implements Rotatable {
// The states of zoom button.
public static final int ZOOM_IN = 0;
public static final int ZOOM_OUT = 1;
@@ -42,7 +42,7 @@ public abstract class ZoomControl extends RelativeLayout {
protected ImageView mZoomOut;
protected ImageView mZoomSlider;
protected int mSliderPosition = 0;
- protected int mDegree;
+ protected int mOrientation;
private Handler mHandler;
public interface OnZoomChangedListener {
@@ -208,13 +208,13 @@ public abstract class ZoomControl extends RelativeLayout {
return true;
}
- public void setDegree(int degree) {
- mDegree = degree;
+ public void setOrientation(int orientation) {
+ mOrientation = orientation;
int count = getChildCount();
for (int i = 0 ; i < count ; ++i) {
View view = getChildAt(i);
if (view instanceof RotateImageView) {
- ((RotateImageView) view).setDegree(degree);
+ ((RotateImageView) view).setOrientation(orientation);
}
}
}
diff --git a/src/com/android/camera/ui/ZoomControlBar.java b/src/com/android/camera/ui/ZoomControlBar.java
index 08042d4..4e572cf 100644
--- a/src/com/android/camera/ui/ZoomControlBar.java
+++ b/src/com/android/camera/ui/ZoomControlBar.java
@@ -36,9 +36,9 @@ public class ZoomControlBar extends ZoomControl {
private View mBar;
private boolean mStartChanging;
private int mSliderLength;
- private int mHeight;
- private int mIconHeight;
- private int mTotalIconHeight;
+ private int mWidth;
+ private int mIconWidth;
+ private int mTotalIconWidth;
public ZoomControlBar(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -53,16 +53,16 @@ public class ZoomControlBar extends ZoomControl {
mBar.setActivated(activated);
}
- private int getSliderPosition(int y) {
+ private int getSliderPosition(int x) {
// Calculate the absolute offset of the slider in the zoom control bar.
// For left-hand users, as the device is rotated for 180 degree for
// landscape mode, the zoom-in bottom should be on the top, so the
// position should be reversed.
int pos; // the relative position in the zoom slider bar
- if (mDegree == 180) {
- pos = y - mTotalIconHeight;
+ if (mOrientation == 90) {
+ pos = mWidth - mTotalIconWidth - x;
} else {
- pos = mHeight - mTotalIconHeight - y;
+ pos = x - mTotalIconWidth;
}
if (pos < 0) pos = 0;
if (pos > mSliderLength) pos = mSliderLength;
@@ -71,15 +71,15 @@ public class ZoomControlBar extends ZoomControl {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- mHeight = h;
- mIconHeight = mZoomIn.getMeasuredHeight();
- mTotalIconHeight = mIconHeight + ICON_SPACING;
- mSliderLength = mHeight - (2 * mTotalIconHeight);
+ mWidth = w;
+ mIconWidth = mZoomIn.getMeasuredWidth();
+ mTotalIconWidth = mIconWidth + ICON_SPACING;
+ mSliderLength = mWidth - (2 * mTotalIconWidth);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
- if (!isEnabled() || (mHeight == 0)) return false;
+ if (!isEnabled() || (mWidth == 0)) return false;
int action = event.getAction();
switch (action) {
@@ -94,7 +94,7 @@ public class ZoomControlBar extends ZoomControl {
setActivated(true);
mStartChanging = false;
case MotionEvent.ACTION_MOVE:
- int pos = getSliderPosition((int) event.getY());
+ int pos = getSliderPosition((int) event.getX());
if (!mStartChanging) {
// Make sure the movement is large enough before we start
// changing the zoom.
@@ -114,18 +114,18 @@ public class ZoomControlBar extends ZoomControl {
}
@Override
- public void setDegree(int degree) {
+ public void setOrientation(int orientation) {
// layout for the left-hand camera control
- if ((degree == 180) || (mDegree == 180)) requestLayout();
- super.setDegree(degree);
+ if ((orientation == 90) || (mOrientation == 90)) requestLayout();
+ super.setOrientation(orientation);
}
@Override
protected void onLayout(
boolean changed, int left, int top, int right, int bottom) {
if (mZoomMax == 0) return;
- int width = right - left;
- mBar.layout(0, mTotalIconHeight, width, mHeight - mTotalIconHeight);
+ int height = bottom - top;
+ mBar.layout(mTotalIconWidth, 0, mWidth - mTotalIconWidth, height);
// For left-hand users, as the device is rotated for 180 degree,
// the zoom-in button should be on the top.
int pos; // slider position
@@ -135,18 +135,18 @@ public class ZoomControlBar extends ZoomControl {
} else {
sliderPosition = (int) ((double) mSliderLength * mZoomIndex / mZoomMax);
}
- if (mDegree == 180) {
- mZoomOut.layout(0, 0, width, mIconHeight);
- mZoomIn.layout(0, mHeight - mIconHeight, width, mHeight);
- pos = mBar.getTop() + sliderPosition;
+ if (mOrientation == 90) {
+ mZoomIn.layout(0, 0, mIconWidth, height);
+ mZoomOut.layout(mWidth - mIconWidth, 0, mWidth, height);
+ pos = mBar.getRight() - sliderPosition;
} else {
- mZoomIn.layout(0, 0, width, mIconHeight);
- mZoomOut.layout(0, mHeight - mIconHeight, width, mHeight);
- pos = mBar.getBottom() - sliderPosition;
+ mZoomOut.layout(0, 0, mIconWidth, height);
+ mZoomIn.layout(mWidth - mIconWidth, 0, mWidth, height);
+ pos = mBar.getLeft() + sliderPosition;
}
- int sliderHeight = mZoomSlider.getMeasuredHeight();
- mZoomSlider.layout(0, (pos - sliderHeight / 2),
- width, (pos + sliderHeight / 2));
+ int sliderWidth = mZoomSlider.getMeasuredWidth();
+ mZoomSlider.layout((pos - sliderWidth / 2), 0,
+ (pos + sliderWidth / 2), height);
}
@Override