blob: 118359442f991a86e2bbcf4c888a06acc3a95cff [file] [log] [blame]
/*
* 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.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import com.android.camera.MultiToggleImageButton;
import com.android.camera.ui.RadioOptions;
import com.android.camera.ui.TopRightWeightedLayout;
import com.android.camera.util.Gusterpolator;
import com.android.camera2.R;
import java.util.ArrayList;
public class ModeOptions extends FrameLayout {
private int mBackgroundColor;
private final Paint mPaint = new Paint();
private boolean mIsHiddenOrHiding;
private RectF mAnimateFrom = new RectF();
private View mViewToShowHide;
private TopRightWeightedLayout mModeOptionsButtons;
private RadioOptions mModeOptionsPano;
private RadioOptions mModeOptionsExposure;
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 = 350;
private ViewGroup mMainBar;
private ViewGroup mActiveBar;
public static final int BAR_INVALID = -1;
public static final int BAR_STANDARD = 0;
public static final int BAR_PANO = 1;
private boolean mIsPortrait;
private float mRadius = 0f;
public ModeOptions(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setViewToShowHide(View v) {
mViewToShowHide = v;
}
@Override
public void onFinishInflate() {
mIsHiddenOrHiding = true;
mBackgroundColor = getResources().getColor(R.color.mode_options_background);
mPaint.setAntiAlias(true);
mPaint.setColor(mBackgroundColor);
mModeOptionsButtons = (TopRightWeightedLayout) findViewById(R.id.mode_options_buttons);
mModeOptionsPano = (RadioOptions) findViewById(R.id.mode_options_pano);
mModeOptionsExposure = (RadioOptions) findViewById(R.id.mode_options_exposure);
mMainBar = mActiveBar = mModeOptionsButtons;
ImageButton exposureButton = (ImageButton) findViewById(R.id.exposure_button);
exposureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mActiveBar = mModeOptionsExposure;
mMainBar.setVisibility(View.INVISIBLE);
mActiveBar.setVisibility(View.VISIBLE);
}
});
}
public void setMainBar(int b) {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setVisibility(View.INVISIBLE);
}
switch (b) {
case BAR_STANDARD:
mMainBar = mActiveBar = mModeOptionsButtons;
break;
case BAR_PANO:
mMainBar = mActiveBar = mModeOptionsPano;
break;
}
mMainBar.setVisibility(View.VISIBLE);
}
public int getMainBar() {
if (mMainBar == mModeOptionsButtons) {
return BAR_STANDARD;
}
if (mMainBar == mModeOptionsPano) {
return BAR_PANO;
}
return BAR_INVALID;
}
@Override
public void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility != VISIBLE && !mIsHiddenOrHiding) {
// Collapse mode options when window is not visible.
setVisibility(INVISIBLE);
if (mMainBar != null) {
mMainBar.setVisibility(VISIBLE);
}
if (mActiveBar != null && mActiveBar != mMainBar) {
mActiveBar.setVisibility(INVISIBLE);
}
if (mViewToShowHide != null) {
mViewToShowHide.setVisibility(VISIBLE);
}
mIsHiddenOrHiding = true;
}
}
@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;
if (mIsPortrait) {
rLeft = getWidth() - buttonPadding - buttonSize;
rTop = (getHeight() - buttonSize) / 2.0f;
} else {
rLeft = buttonPadding;
rTop = buttonPadding;
}
rRight = rLeft + buttonSize;
rBottom = rTop + buttonSize;
mAnimateFrom.set(rLeft, rTop, rRight, rBottom);
setupAnimators();
setupToggleButtonParams();
}
super.onLayout(changed, left, top, right, bottom);
}
@Override
public void onDraw(Canvas canvas) {
if (mDrawCircle) {
canvas.drawCircle(mAnimateFrom.centerX(), mAnimateFrom.centerY(), mRadius, mPaint);
} else if (mFill) {
canvas.drawPaint(mPaint);
}
super.onDraw(canvas);
}
private void setupToggleButtonParams() {
int size = (mIsPortrait ? getHeight() : getWidth());
for (int i = 0; i < mModeOptionsButtons.getChildCount(); i++) {
View button = mModeOptionsButtons.getChildAt(i);
if (button instanceof MultiToggleImageButton) {
MultiToggleImageButton toggleButton = (MultiToggleImageButton) button;
toggleButton.setParentSize(size);
toggleButton.setAnimDirection(mIsPortrait ?
MultiToggleImageButton.ANIM_DIRECTION_VERTICAL :
MultiToggleImageButton.ANIM_DIRECTION_HORIZONTAL);
}
}
}
private void setupAnimators() {
if (mVisibleAnimator != null) {
mVisibleAnimator.end();
}
if (mHiddenAnimator != null) {
mHiddenAnimator.end();
}
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) {
mRadius = (Float) animation.getAnimatedValue();
mDrawCircle = true;
mFill = false;
}
});
radiusAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mDrawCircle = false;
mFill = true;
}
});
final ValueAnimator alphaAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
alphaAnimator.setDuration(SHOW_ALPHA_ANIMATION_TIME);
alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mActiveBar.setAlpha((Float) animation.getAnimatedValue());
}
});
alphaAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mActiveBar.setAlpha(1.0f);
}
});
final int deltaX = getResources()
.getDimensionPixelSize(R.dimen.mode_options_buttons_anim_delta_x);
int childCount = mActiveBar.getChildCount();
ArrayList<Animator> paddingAnimators = new ArrayList<Animator>();
for (int i = 0; i < childCount; i++) {
final View button;
if (mIsPortrait) {
button = mActiveBar.getChildAt(i);
} else {
button = mActiveBar.getChildAt(childCount-1-i);
}
final ValueAnimator paddingAnimator =
ValueAnimator.ofFloat(deltaX*(childCount-i), 0.0f);
paddingAnimator.setDuration(PADDING_ANIMATION_TIME);
paddingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (mIsPortrait) {
button.setTranslationX((Float) animation.getAnimatedValue());
} else {
button.setTranslationY(-((Float) animation.getAnimatedValue()));
}
invalidate();
}
});
paddingAnimators.add(paddingAnimator);
}
AnimatorSet paddingAnimatorSet = new AnimatorSet();
paddingAnimatorSet.playTogether(paddingAnimators);
mVisibleAnimator = new AnimatorSet();
mVisibleAnimator.setInterpolator(Gusterpolator.INSTANCE);
mVisibleAnimator.playTogether(radiusAnimator, alphaAnimator, paddingAnimatorSet);
}
// 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) {
mRadius = (Float) animation.getAnimatedValue();
mDrawCircle = true;
mFill = false;
invalidate();
}
});
radiusAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mViewToShowHide != null) {
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) {
mActiveBar.setAlpha((Float) animation.getAnimatedValue());
invalidate();
}
});
alphaAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(View.INVISIBLE);
if (mActiveBar != mMainBar) {
mActiveBar.setAlpha(1.0f);
mActiveBar.setVisibility(View.INVISIBLE);
}
mMainBar.setAlpha(1.0f);
mMainBar.setVisibility(View.VISIBLE);
mActiveBar = mMainBar;
invalidate();
}
});
mHiddenAnimator = new AnimatorSet();
mHiddenAnimator.setInterpolator(Gusterpolator.INSTANCE);
mHiddenAnimator.playTogether(radiusAnimator, alphaAnimator);
}
}
public void animateVisible() {
if (mIsHiddenOrHiding) {
if (mViewToShowHide != null) {
mViewToShowHide.setVisibility(View.INVISIBLE);
}
mHiddenAnimator.cancel();
mVisibleAnimator.end();
setVisibility(View.VISIBLE);
mVisibleAnimator.start();
}
mIsHiddenOrHiding = false;
}
public void animateHidden() {
if (!mIsHiddenOrHiding) {
mVisibleAnimator.cancel();
mHiddenAnimator.end();
mHiddenAnimator.start();
}
mIsHiddenOrHiding = true;
}
}