/* * 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.FrameLayout.LayoutParams; import android.widget.LinearLayout; import com.android.gallery3d.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); } @Override public void onConfigurationChanged(Configuration config) { if (showsPopup()) { ((ViewGroup) mParent).removeView(mPopup); mPopup = null; initPopup(); mPopup.setVisibility(View.VISIBLE); } } 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); ((ViewGroup) mParent).removeView(mPopup); mPopup = null; } } }; } 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; } }