diff options
author | Spike Sprague <spikuru@google.com> | 2014-02-27 14:33:21 -0800 |
---|---|---|
committer | Spike Sprague <spikuru@google.com> | 2014-03-04 14:09:28 -0800 |
commit | 82fa6ae85f7c07fef480eb1cd0cf7f578b150676 (patch) | |
tree | f0ec7afe0ad03c731c83609f2536bf7a78f83e79 /src | |
parent | 19259ea42f1ff0537847c9b5b3c01b4d0433a7d4 (diff) | |
download | android_packages_apps_Camera2-82fa6ae85f7c07fef480eb1cd0cf7f578b150676.tar.gz android_packages_apps_Camera2-82fa6ae85f7c07fef480eb1cd0cf7f578b150676.tar.bz2 android_packages_apps_Camera2-82fa6ae85f7c07fef480eb1cd0cf7f578b150676.zip |
implement capture options animation
bug: 13100962
Change-Id: I1baf64693d0e01e99bfa19d0bd8699fd33d5812a
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/camera/widget/ModeOptions.java | 295 | ||||
-rw-r--r-- | src/com/android/camera/widget/ModeOptionsOverlay.java | 21 |
2 files changed, 305 insertions, 11 deletions
diff --git a/src/com/android/camera/widget/ModeOptions.java b/src/com/android/camera/widget/ModeOptions.java new file mode 100644 index 000000000..3233d196d --- /dev/null +++ b/src/com/android/camera/widget/ModeOptions.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2014 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.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.util.AttributeSet; + +import com.android.camera.util.Gusterpolator; +import com.android.camera2.R; + +public class ModeOptions extends FrameLayout { + private int mBackgroundColor; + private final Paint mPaint = new Paint(); + private final Path mPath = new Path(); + private boolean mIsHidden; + private RectF mAnimateFrom = new RectF(); + private View mViewToShowHide; + private View mModeOptionsButtons; + + private AnimatorSet mVisibleAnimator; + private AnimatorSet mHiddenAnimator; + private boolean mDrawCircle; + private boolean mFill; + private static final int RADIUS_ANIMATION_TIME = 250; + private static final int SHOW_ALPHA_ANIMATION_TIME = 350; + private static final int HIDE_ALPHA_ANIMATION_TIME = 200; + private static final int PADDING_ANIMATION_TIME = 90; + + private int mParentSize; + private boolean mIsPortrait; + + public ModeOptions(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setViewToShowHide(View v) { + mViewToShowHide = v; + } + + @Override + public void onFinishInflate() { + mBackgroundColor = getResources().getColor(R.color.mode_options_background); + mPaint.setAntiAlias(true); + mPaint.setColor(mBackgroundColor); + mModeOptionsButtons = findViewById(R.id.mode_options_buttons); + } + + @Override + public void onConfigurationChanged(Configuration config) { + super.onConfigurationChanged(config); + + FrameLayout.LayoutParams params = + (FrameLayout.LayoutParams) mModeOptionsButtons.getLayoutParams(); + + if (config.orientation == Configuration.ORIENTATION_PORTRAIT) { + params.gravity = Gravity.RIGHT; + } else { + params.gravity = Gravity.TOP; + } + + mVisibleAnimator.end(); + mHiddenAnimator.end(); + + mModeOptionsButtons.setLayoutParams(params); + } + + + @Override + public void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (changed) { + mIsPortrait = (getResources().getConfiguration().orientation == + Configuration.ORIENTATION_PORTRAIT); + + int buttonSize = getResources() + .getDimensionPixelSize(R.dimen.option_button_circle_size); + int buttonPadding = getResources() + .getDimensionPixelSize(R.dimen.mode_options_toggle_padding); + + float rLeft, rRight, rTop, rBottom; + View parent = (View) getParent(); + if (mIsPortrait) { + rLeft = getWidth() - buttonPadding - buttonSize; + rTop = (getHeight() - buttonSize) / 2.0f; + + mParentSize = parent.getWidth(); + } else { + rLeft = buttonPadding; + rTop = buttonPadding; + + mParentSize = parent.getHeight(); + } + rRight = rLeft + buttonSize; + rBottom = rTop + buttonSize; + mAnimateFrom.set(rLeft, rTop, rRight, rBottom); + + setupAnimators(); + } + + super.onLayout(changed, left, top, right, bottom); + } + + public boolean isHidden() { + return mIsHidden; + } + + @Override + public void onDraw(Canvas canvas) { + if (mDrawCircle) { + canvas.drawPath(mPath, mPaint); + } else if (mFill) { + canvas.drawPaint(mPaint); + } + super.onDraw(canvas); + } + + private void setupAnimators() { + final float fullSize = (mIsPortrait ? (float) getWidth() : (float) getHeight()); + + // show + { + final ValueAnimator radiusAnimator = + ValueAnimator.ofFloat(mAnimateFrom.width()/2.0f, + fullSize-mAnimateFrom.width()/2.0f); + radiusAnimator.setDuration(RADIUS_ANIMATION_TIME); + radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mPath.reset(); + mPath.addCircle(mAnimateFrom.centerX(), + mAnimateFrom.centerY(), + (Float) animation.getAnimatedValue(), + Path.Direction.CW); + mDrawCircle = true; + mFill = false; + invalidate(); + } + }); + radiusAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mPath.reset(); + mDrawCircle = false; + mFill = true; + invalidate(); + } + }); + + final ValueAnimator alphaAnimator = ValueAnimator.ofFloat(1.0f, 1.0f); + alphaAnimator.setDuration(SHOW_ALPHA_ANIMATION_TIME); + alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mModeOptionsButtons.setAlpha((Float) animation.getAnimatedValue()); + invalidate(); + } + }); + alphaAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mModeOptionsButtons.setAlpha(1.0f); + invalidate(); + } + }); + + final ValueAnimator paddingAnimator = ValueAnimator.ofInt(mParentSize, 0); + paddingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + if (mIsPortrait) { + mModeOptionsButtons + .setPadding((Integer) animation.getAnimatedValue(), 0, 0, 0); + } else { + mModeOptionsButtons + .setPadding(0, 0, 0, (Integer) animation.getAnimatedValue()); + } + requestLayout(); + invalidate(); + } + }); + paddingAnimator.setDuration(PADDING_ANIMATION_TIME); + paddingAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mModeOptionsButtons + .setPadding(0, 0, 0, 0); + + requestLayout(); + invalidate(); + } + }); + + mVisibleAnimator = new AnimatorSet(); + mVisibleAnimator.setInterpolator(Gusterpolator.INSTANCE); + mVisibleAnimator.playTogether(radiusAnimator, alphaAnimator, paddingAnimator); + } + + // hide + { + final ValueAnimator radiusAnimator = + ValueAnimator.ofFloat(fullSize-mAnimateFrom.width()/2.0f, + mAnimateFrom.width()/2.0f); + radiusAnimator.setDuration(RADIUS_ANIMATION_TIME); + radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mPath.reset(); + mPath.addCircle(mAnimateFrom.centerX(), + mAnimateFrom.centerY(), + (Float) animation.getAnimatedValue(), + Path.Direction.CW); + mDrawCircle = true; + mFill = false; + invalidate(); + } + }); + radiusAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (mViewToShowHide != null) { + mPath.reset(); + mViewToShowHide.setVisibility(View.VISIBLE); + mDrawCircle = false; + mFill = false; + invalidate(); + } + } + }); + + final ValueAnimator alphaAnimator = ValueAnimator.ofFloat(1.0f, 0.0f); + alphaAnimator.setDuration(HIDE_ALPHA_ANIMATION_TIME); + alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mModeOptionsButtons.setAlpha((Float) animation.getAnimatedValue()); + invalidate(); + } + }); + alphaAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mModeOptionsButtons.setAlpha(0.0f); + invalidate(); + } + }); + + mHiddenAnimator = new AnimatorSet(); + mHiddenAnimator.setInterpolator(Gusterpolator.INSTANCE); + mHiddenAnimator.playTogether(radiusAnimator, alphaAnimator); + } + } + + public void animateVisible() { + mIsHidden = false; + if (mViewToShowHide != null) { + mViewToShowHide.setVisibility(View.INVISIBLE); + } + mHiddenAnimator.cancel(); + mVisibleAnimator.end(); + mVisibleAnimator.start(); + } + + public void animateHidden() { + mIsHidden = true; + mVisibleAnimator.cancel(); + mHiddenAnimator.end(); + mHiddenAnimator.start(); + } +}
\ No newline at end of file diff --git a/src/com/android/camera/widget/ModeOptionsOverlay.java b/src/com/android/camera/widget/ModeOptionsOverlay.java index b7bb681d3..bd988dab2 100644 --- a/src/com/android/camera/widget/ModeOptionsOverlay.java +++ b/src/com/android/camera/widget/ModeOptionsOverlay.java @@ -56,7 +56,7 @@ public class ModeOptionsOverlay extends FrameLayout private int mPreviewWidth; private int mPreviewHeight; - private TopRightWeightedLayout mModeOptions; + private ModeOptions mModeOptions; // The mode options toggle can be either a default image, or a // group of on screen indicators. @@ -72,7 +72,7 @@ public class ModeOptionsOverlay extends FrameLayout @Override public void onFinishInflate() { - mModeOptions = (TopRightWeightedLayout) findViewById(R.id.mode_options); + mModeOptions = (ModeOptions) findViewById(R.id.mode_options); mModeOptions.setClickable(true); mModeOptions.setOnClickListener(new View.OnClickListener() { @Override @@ -83,12 +83,12 @@ public class ModeOptionsOverlay extends FrameLayout mModeOptionsToggle = (FrameLayout) findViewById(R.id.mode_options_toggle); mModeOptionsToggle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mModeOptionsToggle.setVisibility(View.INVISIBLE); - mModeOptions.setVisibility(View.VISIBLE); - } - }); + @Override + public void onClick(View v) { + mModeOptions.animateVisible(); + } + }); + mModeOptions.setViewToShowHide(mModeOptionsToggle); mThreeDots = (ImageView) findViewById(R.id.three_dots); mIndicators = (LinearLayout) findViewById(R.id.indicator_icons); @@ -121,11 +121,10 @@ public class ModeOptionsOverlay extends FrameLayout */ private void closeModeOptions() { // Check that the bottom bar options are visible. - if (mModeOptions.getVisibility() != View.VISIBLE) { + if (mModeOptions.isHidden()) { return; } - mModeOptions.setVisibility(View.INVISIBLE); - mModeOptionsToggle.setVisibility(View.VISIBLE); + mModeOptions.animateHidden(); } @Override |