blob: 7b9fb6499fa8e30e7e436b065ac442a7e6137570 [file] [log] [blame]
/*
* Copyright (C) 2012 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.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.android.camera.R;
import com.android.gallery3d.common.ApiHelper;
public class CameraSwitcher extends RotateImageView
implements OnClickListener, OnTouchListener {
private static final String TAG = "CAM_Switcher";
private static final int SWITCHER_POPUP_ANIM_DURATION = 200;
public interface CameraSwitchListener {
public void onCameraSelected(int i);
public void onShowSwitcherPopup();
}
private CameraSwitchListener mListener;
private int mCurrentIndex;
private int[] mModuleIds;
private int[] mDrawIds;
private int mItemSize;
private View mPopup;
private View mParent;
private boolean mShowingPopup;
private boolean mNeedsAnimationSetup;
private Drawable mIndicator;
private float mTranslationX = 0;
private float mTranslationY = 0;
private AnimatorListener mHideAnimationListener;
private AnimatorListener mShowAnimationListener;
public CameraSwitcher(Context context) {
super(context);
init(context);
}
public CameraSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mItemSize = context.getResources().getDimensionPixelSize(R.dimen.switcher_size);
setOnClickListener(this);
mIndicator = context.getResources().getDrawable(R.drawable.ic_switcher_menu_indicator);
}
public void setIds(int[] moduleids, int[] drawids) {
mDrawIds = drawids;
mModuleIds = moduleids;
}
public void setCurrentIndex(int i) {
mCurrentIndex = i;
setImageResource(mDrawIds[i]);
}
public void setSwitchListener(CameraSwitchListener l) {
mListener = l;
}
@Override
public void onClick(View v) {
showSwitcher();
mListener.onShowSwitcherPopup();
}
private void onCameraSelected(int ix) {
hidePopup();
if ((ix != mCurrentIndex) && (mListener != null)) {
setCurrentIndex(ix);
mListener.onCameraSelected(mModuleIds[ix]);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mIndicator.setBounds(getDrawable().getBounds());
mIndicator.draw(canvas);
}
private void initPopup() {
mParent = LayoutInflater.from(getContext()).inflate(R.layout.switcher_popup,
(ViewGroup) getParent());
LinearLayout content = (LinearLayout) mParent.findViewById(R.id.content);
mPopup = content;
mPopup.setVisibility(View.INVISIBLE);
mNeedsAnimationSetup = true;
for (int i = mDrawIds.length - 1; i >= 0; i--) {
RotateImageView item = new RotateImageView(getContext());
item.setImageResource(mDrawIds[i]);
item.setBackgroundResource(R.drawable.bg_pressed);
final int index = i;
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onCameraSelected(index);
}
});
switch (mDrawIds[i]) {
case R.drawable.ic_switch_camera:
item.setContentDescription(getContext().getResources().getString(
R.string.accessibility_switch_to_camera));
break;
case R.drawable.ic_switch_video:
item.setContentDescription(getContext().getResources().getString(
R.string.accessibility_switch_to_video));
break;
case R.drawable.ic_switch_pan:
item.setContentDescription(getContext().getResources().getString(
R.string.accessibility_switch_to_panorama));
break;
case R.drawable.ic_switch_photosphere:
item.setContentDescription(getContext().getResources().getString(
R.string.accessibility_switch_to_new_panorama));
break;
default:
break;
}
content.addView(item, new LinearLayout.LayoutParams(mItemSize, mItemSize));
}
}
public boolean showsPopup() {
return mShowingPopup;
}
public boolean isInsidePopup(MotionEvent evt) {
if (!showsPopup()) return false;
return evt.getX() >= mPopup.getLeft()
&& evt.getX() < mPopup.getRight()
&& evt.getY() >= mPopup.getTop()
&& evt.getY() < mPopup.getBottom();
}
private void hidePopup() {
mShowingPopup = false;
setVisibility(View.VISIBLE);
if (mPopup != null && !animateHidePopup()) {
mPopup.setVisibility(View.INVISIBLE);
}
mParent.setOnTouchListener(null);
}
private void showSwitcher() {
mShowingPopup = true;
if (mPopup == null) {
initPopup();
}
mPopup.setVisibility(View.VISIBLE);
if (!animateShowPopup()) {
setVisibility(View.INVISIBLE);
}
mParent.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
closePopup();
return true;
}
public void closePopup() {
if (showsPopup()) {
hidePopup();
}
}
@Override
public void setOrientation(int degree, boolean animate) {
super.setOrientation(degree, animate);
ViewGroup content = (ViewGroup) mPopup;
if (content == null) return;
for (int i = 0; i < content.getChildCount(); i++) {
RotateImageView iv = (RotateImageView) content.getChildAt(i);
iv.setOrientation(degree, animate);
}
}
private void updateInitialTranslations() {
if (getResources().getConfiguration().orientation
== Configuration.ORIENTATION_PORTRAIT) {
mTranslationX = -getWidth() / 2;
mTranslationY = getHeight();
} else {
mTranslationX = getWidth();
mTranslationY = getHeight() / 2;
}
}
private void popupAnimationSetup() {
if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
return;
}
updateInitialTranslations();
mPopup.setScaleX(0.3f);
mPopup.setScaleY(0.3f);
mPopup.setTranslationX(mTranslationX);
mPopup.setTranslationY(mTranslationY);
mNeedsAnimationSetup = false;
}
private boolean animateHidePopup() {
if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
return false;
}
if (mHideAnimationListener == null) {
mHideAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Verify that we weren't canceled
if (!showsPopup()) {
mPopup.setVisibility(View.INVISIBLE);
}
}
};
}
mPopup.animate()
.alpha(0f)
.scaleX(0.3f).scaleY(0.3f)
.translationX(mTranslationX)
.translationY(mTranslationY)
.setDuration(SWITCHER_POPUP_ANIM_DURATION)
.setListener(mHideAnimationListener);
animate().alpha(1f).setDuration(SWITCHER_POPUP_ANIM_DURATION)
.setListener(null);
return true;
}
private boolean animateShowPopup() {
if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
return false;
}
if (mNeedsAnimationSetup) {
popupAnimationSetup();
}
if (mShowAnimationListener == null) {
mShowAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Verify that we weren't canceled
if (showsPopup()) {
setVisibility(View.INVISIBLE);
}
}
};
}
mPopup.animate()
.alpha(1f)
.scaleX(1f).scaleY(1f)
.translationX(0)
.translationY(0)
.setDuration(SWITCHER_POPUP_ANIM_DURATION)
.setListener(null);
animate().alpha(0f).setDuration(SWITCHER_POPUP_ANIM_DURATION)
.setListener(mShowAnimationListener);
return true;
}
}