summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu-cheng Li <wuchengli@google.com>2011-07-04 21:07:15 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-07-04 21:07:15 -0700
commitce4b2726c17024706c21b407f8fe918096697c7d (patch)
tree04a898d9bd860f840e39a9594e21fdfb1c3d55b7
parente295e32b68cf04f0d99138bf4a6d25555f3aef99 (diff)
parentc5e37cbb96b8284203560c51dd5f41c705a21f58 (diff)
downloadLegacyCamera-ce4b2726c17024706c21b407f8fe918096697c7d.zip
LegacyCamera-ce4b2726c17024706c21b407f8fe918096697c7d.tar.gz
LegacyCamera-ce4b2726c17024706c21b407f8fe918096697c7d.tar.bz2
Merge "Add expanded thumbnail in phone UI."
-rw-r--r--res/layout-w1024dp/preview_frame.xml5
-rw-r--r--res/layout/preview_frame.xml5
-rw-r--r--res/layout/share_popup.xml36
-rw-r--r--res/values-w1024dp/dimens.xml4
-rw-r--r--res/values/attrs.xml3
-rw-r--r--res/values/dimens.xml6
-rw-r--r--src/com/android/camera/Camera.java55
-rw-r--r--src/com/android/camera/VideoCamera.java49
-rw-r--r--src/com/android/camera/ui/IndicatorWheel.java29
-rw-r--r--src/com/android/camera/ui/RotateImageView.java1
-rw-r--r--src/com/android/camera/ui/RotateLayout.java117
-rw-r--r--src/com/android/camera/ui/SharePopup.java143
12 files changed, 375 insertions, 78 deletions
diff --git a/res/layout-w1024dp/preview_frame.xml b/res/layout-w1024dp/preview_frame.xml
index e211d25..173be1f 100644
--- a/res/layout-w1024dp/preview_frame.xml
+++ b/res/layout-w1024dp/preview_frame.xml
@@ -50,11 +50,6 @@
android:visibility="invisible"/>
<include layout="@layout/review_thumbnail"/>
<include layout="@layout/review_control"/>
- <ImageView android:id="@+id/review_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone"
- android:background="@android:color/black"/>
</RelativeLayout>
<!-- This is the border of preview and the corner is round. If it is the background,
preview will be on top and the inner corner will be square, which looks bad.
diff --git a/res/layout/preview_frame.xml b/res/layout/preview_frame.xml
index 6cf4dfe..4e95882 100644
--- a/res/layout/preview_frame.xml
+++ b/res/layout/preview_frame.xml
@@ -49,10 +49,5 @@
android:layout_alignParentBottom="true"
android:layout_margin="5dp"
android:visibility="invisible"/>
- <ImageView android:id="@+id/review_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone"
- android:background="@android:color/black"/>
</RelativeLayout>
</com.android.camera.PreviewFrameLayout>
diff --git a/res/layout/share_popup.xml b/res/layout/share_popup.xml
new file mode 100644
index 0000000..93ffd4b
--- /dev/null
+++ b/res/layout/share_popup.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:camera="http://schemas.android.com/apk/res/com.android.camera"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <com.android.camera.ui.RotateLayout
+ android:id="@+id/rotate_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true">
+ <!-- The size of the thumbnail is calculated in SharePopup.java -->
+ <ImageView
+ android:id="@+id/expanded_thumbnail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true"
+ android:scaleType="fitCenter" />
+ </com.android.camera.ui.RotateLayout>
+</RelativeLayout>
diff --git a/res/values-w1024dp/dimens.xml b/res/values-w1024dp/dimens.xml
index cb34a3c..1f92a5b 100644
--- a/res/values-w1024dp/dimens.xml
+++ b/res/values-w1024dp/dimens.xml
@@ -27,4 +27,8 @@
<dimen name="mode_switcher_inner_margin">10dp</dimen>
<dimen name="camera_switcher_margin_right">16dp</dimen>
<dimen name="camera_switcher_margin_bottom">24dp</dimen>
+ <dimen name="share_image_max_width_landscape">480dp</dimen>
+ <dimen name="share_image_max_height_landscape">360dp</dimen>
+ <dimen name="share_image_max_width_portrait">480dp</dimen>
+ <dimen name="share_image_max_height_portrait">480dp</dimen>
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 2ce9d42..567d205 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -34,7 +34,4 @@
<attr name="largeIcons" format="reference" />
<attr name="images" format="reference" />
</declare-styleable>
- <declare-styleable name="InLineSettingPicker">
- <attr name="prefKey" format="string" />
- </declare-styleable>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5ec105b..cd42854 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -18,5 +18,9 @@
*/
-->
<resources>
- <dimen name="hint_y_offset">64dip</dimen>
+ <dimen name="hint_y_offset">64dp</dimen>
+ <dimen name="share_image_max_width_landscape">320dp</dimen>
+ <dimen name="share_image_max_height_landscape">240dp</dimen>
+ <dimen name="share_image_max_width_portrait">240dp</dimen>
+ <dimen name="share_image_max_height_portrait">240dp</dimen>
</resources>
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 29534c3..8f99b23 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -23,6 +23,7 @@ import com.android.camera.ui.GLRootView;
import com.android.camera.ui.HeadUpDisplay;
import com.android.camera.ui.IndicatorWheel;
import com.android.camera.ui.RotateImageView;
+import com.android.camera.ui.SharePopup;
import com.android.camera.ui.ZoomControllerListener;
import com.android.camera.ui.ZoomPicker;
@@ -48,7 +49,6 @@ import android.location.LocationProvider;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -59,6 +59,7 @@ import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.view.GestureDetector;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -72,7 +73,6 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
-import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
@@ -136,9 +136,10 @@ public class Camera extends ActivityBase implements View.OnClickListener,
private Parameters mInitialParams;
private MyOrientationEventListener mOrientationListener;
- // The device orientation in degrees. Default is unknown.
+ // The degrees of the device rotated clockwise from its natural orientation.
private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
- // The orientation compensation for icons and thumbnails.
+ // The orientation compensation for icons and thumbnails. Ex: if the value
+ // is 90, the UI components should be rotated 90 degrees counter-clockwise.
private int mOrientationCompensation = 0;
private ComboPreferences mPreferences;
@@ -165,15 +166,14 @@ public class Camera extends ActivityBase implements View.OnClickListener,
private GLRootView mGLRootView;
- // A button showing the last captured picture thumbnail. Clicking on it
- // goes to gallery.
+ // A button showing the last captured picture thumbnail. Clicking on it will
+ // show the share popup window.
private RotateImageView mThumbnailButton;
+ // A popup window that contains a bigger thumbnail and a list of apps to share.
+ private SharePopup mSharePopup;
// The bitmap of the last captured picture thumbnail and the URI of the
// original picture.
private Thumbnail mThumbnail;
- // An review image having same size as preview. It is displayed when
- // share button is pressed.
- private ImageView mReviewImage;
// A button sharing the last picture.
private RotateImageView mShareButton;
private RotateImageView mCameraSwitchIcon;
@@ -977,7 +977,6 @@ public class Camera extends ActivityBase implements View.OnClickListener,
}
mFocusRectangle = (FocusRectangle) findViewById(R.id.focus_rectangle);
mThumbnailButton = (RotateImageView) findViewById(R.id.review_thumbnail);
- mReviewImage = (ImageView) findViewById(R.id.review_image);
mShareButton = (RotateImageView) findViewById(R.id.btn_share);
mCameraSwitchIcon = (RotateImageView) findViewById(R.id.camera_switch_icon);
mVideoSwitchIcon = (RotateImageView) findViewById(R.id.video_switch_icon);
@@ -1124,12 +1123,12 @@ public class Camera extends ActivityBase implements View.OnClickListener,
final String[] SETTING_KEYS = {
CameraSettings.KEY_FLASH_MODE,
CameraSettings.KEY_WHITE_BALANCE,
+ CameraSettings.KEY_COLOR_EFFECT,
CameraSettings.KEY_SCENE_MODE};
final String[] OTHER_SETTING_KEYS = {
CameraSettings.KEY_RECORD_LOCATION,
CameraSettings.KEY_FOCUS_MODE,
CameraSettings.KEY_EXPOSURE,
- CameraSettings.KEY_COLOR_EFFECT,
CameraSettings.KEY_PICTURE_SIZE,
CameraSettings.KEY_JPEG_QUALITY};
mIndicatorWheel.initialize(this, mPreferenceGroup, SETTING_KEYS,
@@ -1222,18 +1221,17 @@ public class Camera extends ActivityBase implements View.OnClickListener,
if (!mIsImageCaptureIntent) {
setOrientationIndicator(mOrientationCompensation);
}
- if (mHeadUpDisplay != null) {
- mHeadUpDisplay.setOrientation(mOrientationCompensation);
- }
}
}
}
private void setOrientationIndicator(int degree) {
+ if (mHeadUpDisplay != null) mHeadUpDisplay.setOrientation(mOrientationCompensation);
if (mThumbnailButton != null) mThumbnailButton.setDegree(degree);
if (mShareButton != null) mShareButton.setDegree(degree);
if (mCameraSwitchIcon != null) mCameraSwitchIcon.setDegree(degree);
if (mVideoSwitchIcon != null) mVideoSwitchIcon.setDegree(degree);
+ if (mSharePopup != null) mSharePopup.setOrientation(degree);
}
@Override
@@ -1274,7 +1272,9 @@ public class Camera extends ActivityBase implements View.OnClickListener,
gotoGallery();
break;
case R.id.btn_share:
- onShareButtonClicked();
+ if (isCameraIdle() && mThumbnail != null) {
+ createSharePopup();
+ }
break;
}
}
@@ -1456,8 +1456,6 @@ public class Camera extends ActivityBase implements View.OnClickListener,
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
- mReviewImage.setVisibility(View.GONE);
-
// Start the preview if it is not started.
if (mCameraState == PREVIEW_STOPPED) {
try {
@@ -1517,6 +1515,8 @@ public class Camera extends ActivityBase implements View.OnClickListener,
hidePostCaptureAlert();
}
+ dismissSharePopup();
+
if (mDidRegister) {
unregisterReceiver(mReceiver);
mDidRegister = false;
@@ -2444,14 +2444,25 @@ public class Camera extends ActivityBase implements View.OnClickListener,
mNotSelectableToast.show();
}
+ private void createSharePopup() {
+ if (mSharePopup != null) mSharePopup.dismiss();
+ mSharePopup = new SharePopup(this, mThumbnail.getUri(),
+ mThumbnail.getBitmap(), mOrientationCompensation, mThumbnailButton);
+ mSharePopup.showAtLocation(mThumbnailButton, Gravity.NO_GRAVITY, 0, 0);
+ }
+
+ private void dismissSharePopup() {
+ if (mSharePopup != null) {
+ mSharePopup.dismiss();
+ mSharePopup = null;
+ }
+ }
+
private void onShareButtonClicked() {
if (mPausing) return;
// Share the last captured picture.
if (mThumbnail != null) {
- mReviewImage.setImageBitmap(mThumbnail.getBitmap());
- mReviewImage.setVisibility(View.VISIBLE);
-
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_STREAM, mThumbnail.getUri());
@@ -2477,10 +2488,6 @@ public class Camera extends ActivityBase implements View.OnClickListener,
public void onOverriddenPreferencesClicked() {
Camera.this.onOverriddenPreferencesClicked();
}
-
- public void onShareButtonClicked() {
- Camera.this.onShareButtonClicked();
- }
}
private class MyCameraPickerListener implements CameraPicker.Listener {
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 6dcb42d..d1a81ae 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -22,6 +22,7 @@ import com.android.camera.ui.GLRootView;
import com.android.camera.ui.HeadUpDisplay;
import com.android.camera.ui.IndicatorWheel;
import com.android.camera.ui.RotateImageView;
+import com.android.camera.ui.SharePopup;
import com.android.camera.ui.ZoomPicker;
import android.content.ActivityNotFoundException;
@@ -40,7 +41,6 @@ import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.media.ThumbnailUtils;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -51,6 +51,7 @@ import android.provider.MediaStore.Video;
import android.provider.Settings;
import android.util.Log;
import android.view.GestureDetector;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -149,14 +150,16 @@ public class VideoCamera extends ActivityBase
private View mReviewControl;
private Toast mNoShareToast;
- // A button showing the last captured video thumbnail. Clicking on it
- // goes to gallery.
+ // A button showing the last captured video thumbnail. Clicking on it will
+ // show the share popup window.
private RotateImageView mThumbnailButton;
+ // A popup window that contains a bigger thumbnail and a list of apps to share.
+ private SharePopup mSharePopup;
// The bitmap of the last captured video thumbnail and the URI of the
// original video.
private Thumbnail mThumbnail;
// An review image having same size as preview. It is displayed when
- // recording is stopped in capture intent or share button is pressed.
+ // recording is stopped in capture intent.
private ImageView mReviewImage;
// A button sharing the last picture.
private RotateImageView mShareButton;
@@ -232,9 +235,10 @@ public class VideoCamera extends ActivityBase
private GestureDetector mPopupGestureDetector;
private MyOrientationEventListener mOrientationListener;
- // The device orientation in degrees. Default is unknown.
+ // The degrees of the device rotated clockwise from its natural orientation.
private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
- // The orientation compensation for icons and thumbnails.
+ // The orientation compensation for icons and thumbnails. Ex: if the value
+ // is 90, the UI components should be rotated 90 degrees counter-clockwise.
private int mOrientationCompensation = 0;
private int mOrientationHint; // the orientation hint for video playback
@@ -559,11 +563,10 @@ public class VideoCamera extends ActivityBase
final String[] SETTING_KEYS = {
CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE,
+ CameraSettings.KEY_WHITE_BALANCE,
CameraSettings.KEY_VIDEO_QUALITY,
CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL};
- final String[] OTHER_SETTING_KEYS = {
- CameraSettings.KEY_WHITE_BALANCE,
- CameraSettings.KEY_COLOR_EFFECT};
+ final String[] OTHER_SETTING_KEYS = {CameraSettings.KEY_COLOR_EFFECT};
mIndicatorWheel.initialize(this, mPreferenceGroup, SETTING_KEYS, OTHER_SETTING_KEYS);
mIndicatorWheel.setListener(new MyIndicatorWheelListener());
mPopupGestureDetector = new GestureDetector(this,
@@ -597,18 +600,17 @@ public class VideoCamera extends ActivityBase
if (!mIsVideoCaptureIntent) {
setOrientationIndicator(mOrientationCompensation);
}
- if (mHeadUpDisplay != null) {
- mHeadUpDisplay.setOrientation(mOrientationCompensation);
- }
}
}
}
private void setOrientationIndicator(int degree) {
+ if (mHeadUpDisplay != null) mHeadUpDisplay.setOrientation(mOrientationCompensation);
if (mThumbnailButton != null) mThumbnailButton.setDegree(degree);
if (mShareButton != null) mShareButton.setDegree(degree);
if (mCameraSwitchIcon != null) mCameraSwitchIcon.setDegree(degree);
if (mVideoSwitchIcon != null) mVideoSwitchIcon.setDegree(degree);
+ if (mSharePopup != null) mSharePopup.setOrientation(degree);
}
private void startPlayVideoActivity() {
@@ -645,7 +647,9 @@ public class VideoCamera extends ActivityBase
gotoGallery();
break;
case R.id.btn_share:
- onShareButtonClicked();
+ if (!mMediaRecorderRecording && mThumbnail != null) {
+ createSharePopup();
+ }
break;
}
}
@@ -976,6 +980,8 @@ public class VideoCamera extends ActivityBase
finishRecorderAndCloseCamera();
+ dismissSharePopup();
+
if (mReceiver != null) {
unregisterReceiver(mReceiver);
mReceiver = null;
@@ -1922,14 +1928,25 @@ public class VideoCamera extends ActivityBase
}
+ private void createSharePopup() {
+ if (mSharePopup != null) mSharePopup.dismiss();
+ mSharePopup = new SharePopup(this, mThumbnail.getUri(),
+ mThumbnail.getBitmap(), mOrientationCompensation, mThumbnailButton);
+ mSharePopup.showAtLocation(mThumbnailButton, Gravity.NO_GRAVITY, 0, 0);
+ }
+
+ private void dismissSharePopup() {
+ if (mSharePopup != null) {
+ mSharePopup.dismiss();
+ mSharePopup = null;
+ }
+ }
+
private void onShareButtonClicked() {
if (mPausing) return;
// Share the last captured video.
if (mThumbnail != null) {
- mReviewImage.setImageBitmap(mThumbnail.getBitmap());
- mReviewImage.setVisibility(View.VISIBLE);
-
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("video/*");
intent.putExtra(Intent.EXTRA_STREAM, mThumbnail.getUri());
diff --git a/src/com/android/camera/ui/IndicatorWheel.java b/src/com/android/camera/ui/IndicatorWheel.java
index 1a374da..c2d7d3c 100644
--- a/src/com/android/camera/ui/IndicatorWheel.java
+++ b/src/com/android/camera/ui/IndicatorWheel.java
@@ -16,7 +16,6 @@
package com.android.camera.ui;
-import com.android.camera.ComboPreferences;
import com.android.camera.IconListPreference;
import com.android.camera.PreferenceGroup;
import com.android.camera.R;
@@ -26,24 +25,22 @@ import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
-import android.os.Handler;
import android.os.SystemClock;
import android.util.AttributeSet;
-import android.util.Log;
-import android.widget.ImageView;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.ViewGroup;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
import java.util.ArrayList;
/**
* A view that contains shutter button and camera setting indicators. The
* indicators are spreaded around the shutter button. The first child is always
- * the shutter button. The last indicator is always the share button.
+ * the shutter button.
*/
public class IndicatorWheel extends ViewGroup implements
BasicSettingPopup.Listener, OtherSettingsPopup.Listener {
@@ -98,7 +95,6 @@ public class IndicatorWheel extends ViewGroup implements
public void onSharedPreferenceChanged();
public void onRestorePreferencesClicked();
public void onOverriddenPreferencesClicked();
- public void onShareButtonClicked();
}
public void setListener(Listener listener) {
@@ -467,9 +463,6 @@ public class IndicatorWheel extends ViewGroup implements
}
mSettingPopups = new AbstractSettingPopup[len];
- // Add share button. It is always the last one.
- addIndicator(context, R.drawable.ic_viewfinder_share);
-
requestLayout();
}
@@ -494,12 +487,6 @@ public class IndicatorWheel extends ViewGroup implements
}
}
- public void onShareButtonClicked() {
- if (mListener != null) {
- mListener.onShareButtonClicked();
- }
- }
-
private void initializeSettingPopup(int index) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
@@ -527,12 +514,6 @@ public class IndicatorWheel extends ViewGroup implements
private void showSettingPopup(int index) {
if (index == mSelectedIndex) return;
- // The share button is the last indicator.
- if (index == mIndicatorCount - 1) {
- onShareButtonClicked();
- return;
- }
-
if (mSettingPopups[index] == null) initializeSettingPopup(index);
if (mPrevAnimatingView != null) mPrevAnimatingView.clearAnimation();
diff --git a/src/com/android/camera/ui/RotateImageView.java b/src/com/android/camera/ui/RotateImageView.java
index 2d88a47..a76d7bc 100644
--- a/src/com/android/camera/ui/RotateImageView.java
+++ b/src/com/android/camera/ui/RotateImageView.java
@@ -56,6 +56,7 @@ public class RotateImageView extends ImageView {
mEnableAnimation = enable;
}
+ // Rotate the view counter-clockwise
public void setDegree(int degree) {
// make sure in the range of [0, 359]
degree = degree >= 0 ? degree % 360 : degree % 360 + 360;
diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java
new file mode 100644
index 0000000..6e1aa92
--- /dev/null
+++ b/src/com/android/camera/ui/RotateLayout.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 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.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+// A RotateLayout is designed to display a single item and provides the
+// capabilities to rotate the item.
+class RotateLayout extends ViewGroup {
+ private int mOrientation;
+ private View mChild;
+
+ public RotateLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mChild = getChildAt(0);
+ }
+
+ @Override
+ protected void onLayout(
+ boolean change, int left, int top, int right, int bottom) {
+ int width = right - left;
+ int height = bottom - top;
+ switch (mOrientation) {
+ case 0:
+ case 180:
+ mChild.layout(0, 0, width, height);
+ break;
+ case 90:
+ case 270:
+ mChild.layout(0, 0, height, width);
+ break;
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthSpec, int heightSpec) {
+ switch(mOrientation) {
+ case 0:
+ case 180:
+ measureChild(mChild, widthSpec, heightSpec);
+ setMeasuredDimension(mChild.getMeasuredWidth(), mChild.getMeasuredHeight());
+ break;
+ case 90:
+ case 270:
+ measureChild(mChild, heightSpec, widthSpec);
+ setMeasuredDimension(mChild.getMeasuredHeight(), mChild.getMeasuredWidth());
+ break;
+ }
+ }
+
+ @Override
+ public void dispatchDraw(Canvas canvas) {
+ int w = getWidth();
+ int h = getHeight();
+ switch (mOrientation) {
+ case 90:
+ canvas.translate(0, h);
+ canvas.rotate(-mOrientation);
+ break;
+ case 180:
+ canvas.rotate(-mOrientation, w / 2, h / 2);
+ break;
+ case 270:
+ canvas.translate(w, 0);
+ canvas.rotate(-mOrientation);
+ break;
+ }
+ super.dispatchDraw(canvas);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ float x = event.getX();
+ float y = event.getY();
+ float width = getWidth();
+ float height = getHeight();
+ switch (mOrientation) {
+ case 90: event.setLocation(height - y, x); break;
+ case 180: event.setLocation(width - x, height - y); break;
+ case 270: event.setLocation(y, width - x); break;
+ }
+ boolean result = mChild.dispatchTouchEvent(event);
+ event.setLocation(x, y);
+ return result;
+ }
+
+ // Rotate the view counter-clockwise
+ public void setOrientation(int orientation) {
+ orientation = orientation % 360;
+ if (mOrientation == orientation) return;
+ mOrientation = orientation;
+ requestLayout();
+ }
+}
diff --git a/src/com/android/camera/ui/SharePopup.java b/src/com/android/camera/ui/SharePopup.java
new file mode 100644
index 0000000..d182e2d
--- /dev/null
+++ b/src/com/android/camera/ui/SharePopup.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2010 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.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.ColorDrawable;
+import android.net.Uri;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
+import android.widget.PopupWindow;
+
+// 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 {
+ private Context mContext;
+ private Uri mUri;
+
+ // The maximum width of the thumbnail in landscape orientation.
+ private final float mImageMaxWidthLandscape;
+ // The maximum height of the thumbnail in landscape orientation.
+ private final float mImageMaxHeightLandscape;
+ // The maximum width of the thumbnail in portrait orientation.
+ private final float mImageMaxWidthPortrait;
+ // The maximum height of the thumbnail in portrait orientation.
+ private final float mImageMaxHeightPortrait;
+
+ private ImageView mThumbnail;
+ private int mBitmapWidth, mBitmapHeight;
+ private RotateLayout mRotateLayout;
+
+ public SharePopup(Activity activity, Uri uri, Bitmap bitmap, int orientation, View anchor) {
+ super(activity);
+
+ // Initailize variables
+ mContext = activity;
+ mUri = uri;
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ View contentView = inflater.inflate(R.layout.share_popup, null, false);
+ // This is required because popup window is full screen.
+ contentView.setOnTouchListener(this);
+ mRotateLayout = (RotateLayout) contentView.findViewById(R.id.rotate_layout);
+ mThumbnail = (ImageView) contentView.findViewById(R.id.expanded_thumbnail);
+ mThumbnail.setImageBitmap(bitmap);
+ mThumbnail.setOnClickListener(this);
+ mBitmapWidth = bitmap.getWidth();
+ mBitmapHeight = bitmap.getHeight();
+ Resources res = mContext.getResources();
+ mImageMaxWidthLandscape = res.getDimension(R.dimen.share_image_max_width_landscape);
+ mImageMaxHeightLandscape = res.getDimension(R.dimen.share_image_max_height_landscape);
+ mImageMaxWidthPortrait = res.getDimension(R.dimen.share_image_max_width_portrait);
+ mImageMaxHeightPortrait = res.getDimension(R.dimen.share_image_max_height_portrait);
+
+ // Initialize popup window
+ setWidth(WindowManager.LayoutParams.MATCH_PARENT);
+ setHeight(WindowManager.LayoutParams.MATCH_PARENT);
+ setBackgroundDrawable(new ColorDrawable());
+ setContentView(contentView);
+ setOrientation(orientation);
+
+ // Initialize view location
+ int location[] = new int[2];
+ anchor.getLocationOnScreen(location);
+ DisplayMetrics metrics = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ MarginLayoutParams params = (MarginLayoutParams) mRotateLayout.getLayoutParams();
+ params.topMargin = location[1] / 2;
+ params.rightMargin = (metrics.widthPixels - location[0] - anchor.getWidth()) / 2;
+ mRotateLayout.setLayoutParams(params);
+
+ // Start animation
+ Animation fadeIn = AnimationUtils.loadAnimation(mContext, R.anim.grow_fade_in_from_right);
+ mRotateLayout.startAnimation(fadeIn);
+ }
+
+ public void setOrientation(int orientation) {
+ // Calculate the width and the height of the thumbnail.
+ float width, height;
+ if (orientation == 90 || orientation == 270) {
+ width = mImageMaxWidthPortrait;
+ height = mImageMaxHeightPortrait;
+ } else {
+ width = mImageMaxWidthLandscape;
+ height = mImageMaxHeightLandscape;
+ }
+ LayoutParams params = mThumbnail.getLayoutParams();
+ if (width * mBitmapHeight > height * mBitmapWidth) {
+ params.width = Math.round(mBitmapWidth * height / mBitmapHeight);
+ params.height = Math.round(height);
+ } else {
+ params.width = Math.round(width);
+ params.height = Math.round(mBitmapHeight * params.width / mBitmapWidth);
+ }
+ mThumbnail.setLayoutParams(params);
+ mRotateLayout.setOrientation(orientation);
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.expanded_thumbnail:
+ Util.viewUri(mUri, mContext);
+ break;
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ dismiss();
+ return true;
+ }
+ return false;
+ }
+}