package com.android.camera.ui;
import android.content.Context;
+import android.content.res.Configuration;
+import android.view.animation.Interpolator;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.android.camera.CaptureLayoutHelper;
import com.android.camera.debug.Log;
+import com.android.camera.ui.motion.InterpolatorHelper;
+import com.android.camera.widget.ModeOptions;
+import com.android.camera.widget.ModeOptionsOverlay;
import com.android.camera.widget.RoundedThumbnailView;
import com.android.camera2.R;
private final static Log.Tag TAG = new Log.Tag("StickyBotCapLayout");
private RoundedThumbnailView mRoundedThumbnailView;
- private View mModeOptionsOverlay;
+ private ModeOptionsOverlay mModeOptionsOverlay;
private View mBottomBar;
private CaptureLayoutHelper mCaptureLayoutHelper = null;
+ private ModeOptions.Listener mModeOptionsListener = new ModeOptions.Listener() {
+ @Override
+ public void onBeginToShowModeOptions() {
+ final PointF thumbnailViewPosition = getRoundedThumbnailPosition(
+ mCaptureLayoutHelper.getUncoveredPreviewRect(),
+ false,
+ mModeOptionsOverlay.getModeOptionsToggleWidth());
+ final int orientation = getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ animateCaptureIndicatorToY(thumbnailViewPosition.y);
+ } else {
+ animateCaptureIndicatorToX(thumbnailViewPosition.x);
+ }
+ }
+
+ @Override
+ public void onBeginToHideModeOptions() {
+ final PointF thumbnailViewPosition = getRoundedThumbnailPosition(
+ mCaptureLayoutHelper.getUncoveredPreviewRect(),
+ true,
+ mModeOptionsOverlay.getModeOptionsToggleWidth());
+ final int orientation = getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ animateCaptureIndicatorToY(thumbnailViewPosition.y);
+ } else {
+ animateCaptureIndicatorToX(thumbnailViewPosition.x);
+ }
+ }
+ };
+
public StickyBottomCaptureLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onFinishInflate() {
mRoundedThumbnailView = (RoundedThumbnailView) findViewById(R.id.rounded_thumbnail_view);
- mModeOptionsOverlay = findViewById(R.id.mode_options_overlay);
+ mModeOptionsOverlay = (ModeOptionsOverlay) findViewById(R.id.mode_options_overlay);
+ mModeOptionsOverlay.setModeOptionsListener(mModeOptionsListener);
mBottomBar = findViewById(R.id.bottom_bar);
}
Log.e(TAG, "Capture layout helper needs to be set first.");
return;
}
- RectF drawRect = new RectF(left, top, right, bottom);
+ // Layout mode options overlay.
RectF uncoveredPreviewRect = mCaptureLayoutHelper.getUncoveredPreviewRect();
- RectF bottomBarRect = mCaptureLayoutHelper.getBottomBarRect();
- RectF roundedThumbnailViewRect =
- mRoundedThumbnailView.getDesiredLayout(drawRect, uncoveredPreviewRect);
- mRoundedThumbnailView.layout(
- (int) roundedThumbnailViewRect.left,
- (int) roundedThumbnailViewRect.top,
- (int) roundedThumbnailViewRect.right,
- (int) roundedThumbnailViewRect.bottom);
mModeOptionsOverlay.layout((int) uncoveredPreviewRect.left, (int) uncoveredPreviewRect.top,
(int) uncoveredPreviewRect.right, (int) uncoveredPreviewRect.bottom);
+
+ // Layout capture indicator.
+ PointF roundedThumbnailViewPosition = getRoundedThumbnailPosition(
+ uncoveredPreviewRect,
+ mModeOptionsOverlay.isModeOptionsHidden(),
+ mModeOptionsOverlay.getModeOptionsToggleWidth());
+ mRoundedThumbnailView.layout(
+ (int) roundedThumbnailViewPosition.x,
+ (int) roundedThumbnailViewPosition.y,
+ (int) roundedThumbnailViewPosition.x + mRoundedThumbnailView.getMeasuredWidth(),
+ (int) roundedThumbnailViewPosition.y + mRoundedThumbnailView.getMeasuredHeight());
+
+ // Layout bottom bar.
+ RectF bottomBarRect = mCaptureLayoutHelper.getBottomBarRect();
mBottomBar.layout((int) bottomBarRect.left, (int) bottomBarRect.top,
(int) bottomBarRect.right, (int) bottomBarRect.bottom);
}
-}
\ No newline at end of file
+
+ /**
+ * Calculates the desired layout of capture indicator.
+ *
+ * @param uncoveredPreviewRect The uncovered preview bound which contains mode option
+ * overlay and capture indicator.
+ * @param isModeOptionsHidden Whether the mode options button are hidden.
+ * @param modeOptionsToggleWidth The width of mode options toggle (three dots button).
+ * @return the desired view bound for capture indicator.
+ */
+ private PointF getRoundedThumbnailPosition(
+ RectF uncoveredPreviewRect, boolean isModeOptionsHidden, float modeOptionsToggleWidth) {
+ final float threeDotsButtonDiameter =
+ getResources().getDimension(R.dimen.option_button_circle_size);
+ final float threeDotsButtonPadding =
+ getResources().getDimension(R.dimen.mode_options_toggle_padding);
+ final float modeOptionsHeight = getResources().getDimension(R.dimen.mode_options_height);
+
+ final float roundedThumbnailViewSize = mRoundedThumbnailView.getMeasuredWidth();
+ final float roundedThumbnailFinalSize = mRoundedThumbnailView.getThumbnailFinalDiameter();
+ final float roundedThumbnailViewPadding = mRoundedThumbnailView.getThumbnailPadding();
+
+ // The view bound is based on the maximal ripple ring diameter. This is the diff of maximal
+ // ripple ring radius and the final thumbnail radius.
+ final float radiusDiffBetweenViewAndThumbnail =
+ (roundedThumbnailViewSize - roundedThumbnailFinalSize) / 2.0f;
+ final float distanceFromModeOptions = roundedThumbnailViewPadding +
+ roundedThumbnailFinalSize + radiusDiffBetweenViewAndThumbnail;
+
+ final int orientation = getResources().getConfiguration().orientation;
+
+ float x = 0;
+ float y = 0;
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // The view finder of 16:9 aspect ratio might have a black padding.
+ x = uncoveredPreviewRect.right - distanceFromModeOptions;
+
+ y = uncoveredPreviewRect.bottom;
+ if (isModeOptionsHidden) {
+ y -= threeDotsButtonPadding + threeDotsButtonDiameter;
+ } else {
+ y -= modeOptionsHeight;
+ }
+ y -= distanceFromModeOptions;
+ }
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ if (isModeOptionsHidden) {
+ x = uncoveredPreviewRect.right - threeDotsButtonPadding - modeOptionsToggleWidth;
+ } else {
+ x = uncoveredPreviewRect.right - modeOptionsHeight;
+ }
+ x -= distanceFromModeOptions;
+ y = uncoveredPreviewRect.top + roundedThumbnailViewPadding -
+ radiusDiffBetweenViewAndThumbnail;
+ }
+ return new PointF(x, y);
+ }
+
+ private void animateCaptureIndicatorToX(float x) {
+ final Interpolator interpolator =
+ InterpolatorHelper.getLinearOutSlowInInterpolator(getContext());
+ mRoundedThumbnailView.animate()
+ .setDuration(ModeOptions.PADDING_ANIMATION_TIME)
+ .setInterpolator(interpolator)
+ .x(x)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mRoundedThumbnailView.setTranslationX(0.0f);
+ requestLayout();
+ }
+ });
+ }
+
+ private void animateCaptureIndicatorToY(float y) {
+ final Interpolator interpolator =
+ InterpolatorHelper.getLinearOutSlowInInterpolator(getContext());
+ mRoundedThumbnailView.animate()
+ .setDuration(ModeOptions.PADDING_ANIMATION_TIME)
+ .setInterpolator(interpolator)
+ .y(y)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mRoundedThumbnailView.setTranslationY(0.0f);
+ requestLayout();
+ }
+ });
+ }
+}