summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera/ui')
-rw-r--r--src/com/android/camera/ui/CameraRootView.java23
-rw-r--r--src/com/android/camera/ui/FilmStripView.java53
-rw-r--r--src/com/android/camera/ui/PieRenderer.java59
-rw-r--r--src/com/android/camera/ui/ProgressRenderer.java127
4 files changed, 220 insertions, 42 deletions
diff --git a/src/com/android/camera/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java
index 505549c80..daaefc027 100644
--- a/src/com/android/camera/ui/CameraRootView.java
+++ b/src/com/android/camera/ui/CameraRootView.java
@@ -37,7 +37,7 @@ public class CameraRootView extends FrameLayout {
private int mBottomMargin = 0;
private int mLeftMargin = 0;
private int mRightMargin = 0;
- private Rect mCurrentInsets;
+ private final Rect mCurrentInsets = new Rect(0, 0, 0, 0);
private int mOffset = 0;
private Object mDisplayListener;
private MyDisplayListener mListener;
@@ -53,19 +53,24 @@ public class CameraRootView extends FrameLayout {
@Override
protected boolean fitSystemWindows(Rect insets) {
- mCurrentInsets = insets;
// insets include status bar, navigation bar, etc
// In this case, we are only concerned with the size of nav bar
- if (mOffset > 0) {
- return true;
+ if (mCurrentInsets.equals(insets)) {
+ // Local copy of the insets is up to date. No need to do anything.
+ return false;
}
- if (insets.bottom > 0) {
- mOffset = insets.bottom;
- } else if (insets.right > 0) {
- mOffset = insets.right;
+ if (mOffset == 0) {
+ if (insets.bottom > 0) {
+ mOffset = insets.bottom;
+ } else if (insets.right > 0) {
+ mOffset = insets.right;
+ }
}
- return true;
+ mCurrentInsets.set(insets);
+ // Make sure onMeasure will be called to adapt to the new insets.
+ requestLayout();
+ return false;
}
public void initDisplayListener() {
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 9945952ee..89da0184e 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -43,6 +43,7 @@ import com.android.camera.ui.FilmStripView.ImageData.PanoramaSupportCallback;
import com.android.camera.ui.FilmstripBottomControls.BottomControlsListener;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
+import com.android.camera.util.UsageStatistics;
import com.android.camera2.R;
import java.util.Arrays;
@@ -1453,6 +1454,13 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
mController.setSurroundingViewsVisible(true);
}
+ private void hideZoomView() {
+ if (mController.isZoomStarted()) {
+ mController.cancelLoadingZoomedImage();
+ mZoomView.setVisibility(GONE);
+ }
+ }
+
// Keeps the view in the view hierarchy if it's camera preview.
// Remove from the hierarchy otherwise.
private void checkForRemoval(ImageData data, View v) {
@@ -1785,6 +1793,8 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
&& deltaX < mSlop * (-1)) {
// intercept left swipe
if (Math.abs(deltaX) >= Math.abs(deltaY) * 2) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_FILMSTRIP, null);
return true;
}
}
@@ -1908,10 +1918,19 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
mController.stopScrolling(true);
mController.stopScale();
mDataIdOnUserScrolling = 0;
- // Remove all views from the mViewItem buffer, except the camera view.
+ // Reload has a side effect that after this call, it will show the
+ // camera preview. So we want to know whether it starts from the camera
+ // preview to decide whether we need to call onDataFocusChanged.
+ boolean stayInPreview = false;
+
if (mListener != null && mViewItem[mCurrentItem] != null) {
- mListener.onDataFocusChanged(mViewItem[mCurrentItem].getId(), false);
+ stayInPreview = mViewItem[mCurrentItem].getId() == 0;
+ if (!stayInPreview) {
+ mListener.onDataFocusChanged(mViewItem[mCurrentItem].getId(), false);
+ }
}
+
+ // Remove all views from the mViewItem buffer, except the camera view.
for (int i = 0; i < mViewItem.length; i++) {
if (mViewItem[i] == null) {
continue;
@@ -1920,8 +1939,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (v != mCameraView) {
removeView(v);
}
- if (mDataAdapter.getImageData(mViewItem[i].getId()) != null) {
- mDataAdapter.getImageData(mViewItem[i].getId()).recycle();
+ ImageData imageData = mDataAdapter.getImageData(mViewItem[i].getId());
+ if (imageData != null) {
+ imageData.recycle();
}
}
@@ -1954,7 +1974,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (mListener != null) {
mListener.onReload();
- mListener.onDataFocusChanged(mViewItem[mCurrentItem].getId(), true);
+ if (!stayInPreview) {
+ mListener.onDataFocusChanged(mViewItem[mCurrentItem].getId(), true);
+ }
}
}
@@ -2625,13 +2647,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (!mController.stopScrolling(false)) {
return false;
}
- // A down event is usually followed by a gesture, we apply gesture on
- // the lower-res image during a gesture to ensure a responsive experience.
- // TODO: Delay this until gesture starts.
- if (mController.isZoomStarted()) {
- mController.cancelLoadingZoomedImage();
- mZoomView.setVisibility(GONE);
- }
+
return true;
}
@@ -2712,12 +2728,16 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
@Override
public boolean onScroll(float x, float y, float dx, float dy) {
- if (mViewItem[mCurrentItem] == null) {
+ ViewItem currItem = mViewItem[mCurrentItem];
+ if (currItem == null) {
return false;
}
+ if (!mDataAdapter.canSwipeInFullScreen(currItem.getId())) {
+ return false;
+ }
+ hideZoomView();
// When image is zoomed in to be bigger than the screen
if (mController.isZoomStarted()) {
- mController.cancelLoadingZoomedImage();
ViewItem curr = mViewItem[mCurrentItem];
float transX = curr.getTranslationX() - dx;
float transY = curr.getTranslationY() - dy;
@@ -2777,6 +2797,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (currItem == null) {
return false;
}
+ if (!mDataAdapter.canSwipeInFullScreen(currItem.getId())) {
+ return false;
+ }
if (mController.isZoomStarted()) {
// Fling within the zoomed image
mController.flingInsideZoomView(velocityX, velocityY);
@@ -2837,6 +2860,8 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (inCameraFullscreen()) {
return false;
}
+
+ hideZoomView();
mScaleTrend = 1f;
// If the image is smaller than screen size, we should allow to zoom
// in to full screen size
diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java
index 008bc40ca..0039aa22c 100644
--- a/src/com/android/camera/ui/PieRenderer.java
+++ b/src/com/android/camera/ui/PieRenderer.java
@@ -16,9 +16,6 @@
package com.android.camera.ui;
-import java.util.ArrayList;
-import java.util.List;
-
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
@@ -40,12 +37,19 @@ import android.view.animation.Animation;
import android.view.animation.Transformation;
import com.android.camera.drawable.TextDrawable;
+import com.android.camera.ui.ProgressRenderer.VisibilityListener;
import com.android.camera2.R;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An overlay renderer that is used to display focus state and progress state.
+ */
public class PieRenderer extends OverlayRenderer
implements FocusIndicator {
- private static final String TAG = "CAM Pie";
+ private static final String TAG = "PieRenderer";
// Sometimes continuous autofocus starts and stops several times quickly.
// These states are used to make sure the animation is run for at least some
@@ -143,7 +147,7 @@ public class PieRenderer extends OverlayRenderer
private int mAngleZone;
private float mCenterAngle;
-
+ private ProgressRenderer mProgressRenderer;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
@@ -227,6 +231,7 @@ public class PieRenderer extends OverlayRenderer
mLabel.setDropShadow(true);
mDeadZone = res.getDimensionPixelSize(R.dimen.pie_deadzone_width);
mAngleZone = res.getDimensionPixelSize(R.dimen.pie_anglezone_width);
+ mProgressRenderer = new ProgressRenderer(ctx);
}
private PieItem getRoot() {
@@ -309,6 +314,10 @@ public class PieRenderer extends OverlayRenderer
return mState == STATE_PIE && isVisible();
}
+ public void setProgress(int percent) {
+ mProgressRenderer.setProgress(percent);
+ }
+
private void fadeIn() {
mFadeIn = new ValueAnimator();
mFadeIn.setFloatValues(0f, 1f);
@@ -524,6 +533,8 @@ public class PieRenderer extends OverlayRenderer
@Override
public void onDraw(Canvas canvas) {
+ mProgressRenderer.onDraw(canvas, mFocusX, mFocusY);
+
float alpha = 1;
if (mXFade != null) {
alpha = (Float) mXFade.getAnimatedValue();
@@ -706,6 +717,11 @@ public class PieRenderer extends OverlayRenderer
return false;
}
+ @Override
+ public boolean isVisible() {
+ return super.isVisible() || mProgressRenderer.isVisible();
+ }
+
private boolean pulledToCenter(PointF polarCoords) {
return polarCoords.y < mArcRadius - mRadiusInc;
}
@@ -918,17 +934,6 @@ public class PieRenderer extends OverlayRenderer
setCircle(mFocusX, mFocusY);
}
- public void alignFocus(int x, int y) {
- mOverlay.removeCallbacks(mDisappear);
- mAnimation.cancel();
- mAnimation.reset();
- mFocusX = x;
- mFocusY = y;
- mDialAngle = DIAL_HORIZONTAL;
- setCircle(x, y);
- mFocused = false;
- }
-
public int getSize() {
return 2 * mCircleSize;
}
@@ -1022,11 +1027,27 @@ public class PieRenderer extends OverlayRenderer
mState = STATE_IDLE;
}
+ public void clear(boolean waitUntilProgressIsHidden) {
+ if (mState == STATE_PIE)
+ return;
+ cancelFocus();
+
+ if (waitUntilProgressIsHidden) {
+ mProgressRenderer.setVisibilityListener(new VisibilityListener() {
+ @Override
+ public void onHidden() {
+ mOverlay.post(mDisappear);
+ }
+ });
+ } else {
+ mOverlay.post(mDisappear);
+ mProgressRenderer.setVisibilityListener(null);
+ }
+ }
+
@Override
public void clear() {
- if (mState == STATE_PIE) return;
- cancelFocus();
- mOverlay.post(mDisappear);
+ clear(false);
}
private void startAnimation(long duration, boolean timeout,
diff --git a/src/com/android/camera/ui/ProgressRenderer.java b/src/com/android/camera/ui/ProgressRenderer.java
new file mode 100644
index 000000000..500293133
--- /dev/null
+++ b/src/com/android/camera/ui/ProgressRenderer.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+import com.android.camera2.R;
+
+/**
+ * Renders a circular progress bar on the screen.
+ */
+public class ProgressRenderer {
+
+ public static interface VisibilityListener {
+ public void onHidden();
+ }
+
+ private final int mProgressRadius;
+ private final Paint mProgressBasePaint;
+ private final Paint mProgressPaint;
+
+ private RectF mArcBounds = new RectF(0, 0, 1, 1);
+ private int mProgressAngleDegrees = 270;
+ private boolean mVisible = false;
+ private VisibilityListener mVisibilityListener;
+
+ /**
+ * After we reach 100%, keep on painting the progress for another x milliseconds
+ * before hiding it.
+ */
+ private static final int SHOW_PROGRESS_X_ADDITIONAL_MS = 100;
+
+ /** When to hide the progress indicator. */
+ private long mTimeToHide = 0;
+
+ public ProgressRenderer(Context context) {
+ mProgressRadius = context.getResources().getDimensionPixelSize(R.dimen.pie_progress_radius);
+ int pieProgressWidth = context.getResources().getDimensionPixelSize(
+ R.dimen.pie_progress_width);
+ mProgressBasePaint = createProgressPaint(pieProgressWidth, 0.2f);
+ mProgressPaint = createProgressPaint(pieProgressWidth, 1.0f);
+ }
+
+ /**
+ * Sets or replaces a visiblity listener.
+ */
+ public void setVisibilityListener(VisibilityListener listener) {
+ mVisibilityListener = listener;
+ }
+
+ /**
+ * Shows a progress indicator. If the progress is '100', the progress
+ * indicator will be hidden.
+ *
+ * @param percent the progress in percent (0-100).
+ */
+ public void setProgress(int percent) {
+ // Clamp the value.
+ percent = Math.min(100, Math.max(percent, 0));
+ mProgressAngleDegrees = (int) ((360f / 100) * percent);
+
+ // We hide the progress once we drew the 100% state once.
+ if (percent < 100) {
+ mVisible = true;
+ mTimeToHide = System.currentTimeMillis() + SHOW_PROGRESS_X_ADDITIONAL_MS;
+ }
+ }
+
+ /**
+ * Draw the current progress (if < 100%) centered at the given location.
+ */
+ public void onDraw(Canvas canvas, int centerX, int centerY) {
+ if (!mVisible) {
+ return;
+ }
+ mArcBounds = new RectF(centerX - mProgressRadius, centerY - mProgressRadius, centerX
+ + mProgressRadius,
+ centerY + mProgressRadius);
+
+ canvas.drawCircle(centerX, centerY, mProgressRadius, mProgressBasePaint);
+ canvas.drawArc(mArcBounds, -90, mProgressAngleDegrees, false, mProgressPaint);
+
+ // After we reached 100%, we paint the progress renderer for another x
+ // milliseconds until we hide it.
+ if (mProgressAngleDegrees == 360 && System.currentTimeMillis() > mTimeToHide) {
+ mVisible = false;
+ if (mVisibilityListener != null) {
+ mVisibilityListener.onHidden();
+ }
+ }
+ }
+
+ /**
+ * @return Whether the progress renderer is visible.
+ */
+ public boolean isVisible() {
+ return mVisible;
+ }
+
+ private static Paint createProgressPaint(int width, float alpha) {
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ // 20% alpha.
+ paint.setColor(Color.argb((int) (alpha * 255), 255, 255, 255));
+ paint.setStrokeWidth(width);
+ paint.setStyle(Paint.Style.STROKE);
+ return paint;
+ }
+}