Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.ui;
     18 
     19 import android.animation.Animator;
     20 import android.animation.Animator.AnimatorListener;
     21 import android.animation.AnimatorListenerAdapter;
     22 import android.content.Context;
     23 import android.content.res.Configuration;
     24 import android.graphics.Canvas;
     25 import android.graphics.drawable.Drawable;
     26 import android.util.AttributeSet;
     27 import android.view.LayoutInflater;
     28 import android.view.MotionEvent;
     29 import android.view.View;
     30 import android.view.View.OnClickListener;
     31 import android.view.View.OnTouchListener;
     32 import android.view.ViewGroup;
     33 import android.widget.LinearLayout;
     34 
     35 import com.android.camera.R;
     36 import com.android.gallery3d.common.ApiHelper;
     37 
     38 public class CameraSwitcher extends RotateImageView
     39         implements OnClickListener, OnTouchListener {
     40 
     41     private static final String TAG = "CAM_Switcher";
     42     private static final int SWITCHER_POPUP_ANIM_DURATION = 200;
     43 
     44     public interface CameraSwitchListener {
     45         public void onCameraSelected(int i);
     46         public void onShowSwitcherPopup();
     47     }
     48 
     49     private CameraSwitchListener mListener;
     50     private int mCurrentIndex;
     51     private int[] mDrawIds;
     52     private int mItemSize;
     53     private View mPopup;
     54     private View mParent;
     55     private boolean mShowingPopup;
     56     private boolean mNeedsAnimationSetup;
     57     private Drawable mIndicator;
     58 
     59     private float mTranslationX = 0;
     60     private float mTranslationY = 0;
     61 
     62     private AnimatorListener mHideAnimationListener;
     63     private AnimatorListener mShowAnimationListener;
     64 
     65     public CameraSwitcher(Context context) {
     66         super(context);
     67         init(context);
     68     }
     69 
     70     public CameraSwitcher(Context context, AttributeSet attrs) {
     71         super(context, attrs);
     72         init(context);
     73     }
     74 
     75     private void init(Context context) {
     76         mItemSize = context.getResources().getDimensionPixelSize(R.dimen.switcher_size);
     77         setOnClickListener(this);
     78         mIndicator = context.getResources().getDrawable(R.drawable.ic_switcher_menu_indicator);
     79     }
     80 
     81     public void setDrawIds(int[] drawids) {
     82         mDrawIds = drawids;
     83     }
     84 
     85     public void setCurrentIndex(int i) {
     86         mCurrentIndex = i;
     87         setImageResource(mDrawIds[i]);
     88     }
     89 
     90     public void setSwitchListener(CameraSwitchListener l) {
     91         mListener = l;
     92     }
     93 
     94     @Override
     95     public void onClick(View v) {
     96         showSwitcher();
     97         mListener.onShowSwitcherPopup();
     98     }
     99 
    100     private void onCameraSelected(int ix) {
    101         hidePopup();
    102         if ((ix != mCurrentIndex) && (mListener != null)) {
    103             setCurrentIndex(ix);
    104             mListener.onCameraSelected(ix);
    105         }
    106     }
    107 
    108     @Override
    109     protected void onDraw(Canvas canvas) {
    110         super.onDraw(canvas);
    111         mIndicator.setBounds(getDrawable().getBounds());
    112         mIndicator.draw(canvas);
    113     }
    114 
    115     private void initPopup() {
    116         mParent = LayoutInflater.from(getContext()).inflate(R.layout.switcher_popup,
    117                 (ViewGroup) getParent());
    118         LinearLayout content = (LinearLayout) mParent.findViewById(R.id.content);
    119         mPopup = content;
    120         mPopup.setVisibility(View.INVISIBLE);
    121         mNeedsAnimationSetup = true;
    122         for (int i = mDrawIds.length - 1; i >= 0; i--) {
    123             RotateImageView item = new RotateImageView(getContext());
    124             item.setImageResource(mDrawIds[i]);
    125             item.setBackgroundResource(R.drawable.bg_pressed);
    126             final int index = i;
    127             item.setOnClickListener(new OnClickListener() {
    128                 @Override
    129                 public void onClick(View v) {
    130                     onCameraSelected(index);
    131                 }
    132             });
    133             switch (mDrawIds[i]) {
    134                 case R.drawable.ic_switch_camera:
    135                     item.setContentDescription(getContext().getResources().getString(
    136                             R.string.accessibility_switch_to_camera));
    137                     break;
    138                 case R.drawable.ic_switch_video:
    139                     item.setContentDescription(getContext().getResources().getString(
    140                             R.string.accessibility_switch_to_video));
    141                     break;
    142                 case R.drawable.ic_switch_pan:
    143                     item.setContentDescription(getContext().getResources().getString(
    144                             R.string.accessibility_switch_to_panorama));
    145                     break;
    146                 case R.drawable.ic_switch_photosphere:
    147                     item.setContentDescription(getContext().getResources().getString(
    148                             R.string.accessibility_switch_to_new_panorama));
    149                     break;
    150                 default:
    151                     break;
    152             }
    153             content.addView(item, new LinearLayout.LayoutParams(mItemSize, mItemSize));
    154         }
    155     }
    156 
    157     public boolean showsPopup() {
    158         return mShowingPopup;
    159     }
    160 
    161     public boolean isInsidePopup(MotionEvent evt) {
    162         if (!showsPopup()) return false;
    163         return evt.getX() >= mPopup.getLeft()
    164                 && evt.getX() < mPopup.getRight()
    165                 && evt.getY() >= mPopup.getTop()
    166                 && evt.getY() < mPopup.getBottom();
    167     }
    168 
    169     private void hidePopup() {
    170         mShowingPopup = false;
    171         setVisibility(View.VISIBLE);
    172         if (mPopup != null && !animateHidePopup()) {
    173             mPopup.setVisibility(View.INVISIBLE);
    174         }
    175         mParent.setOnTouchListener(null);
    176     }
    177 
    178     private void showSwitcher() {
    179         mShowingPopup = true;
    180         if (mPopup == null) {
    181             initPopup();
    182         }
    183         mPopup.setVisibility(View.VISIBLE);
    184         if (!animateShowPopup()) {
    185             setVisibility(View.INVISIBLE);
    186         }
    187         mParent.setOnTouchListener(this);
    188     }
    189 
    190     @Override
    191     public boolean onTouch(View v, MotionEvent event) {
    192         closePopup();
    193         return true;
    194     }
    195 
    196     public void closePopup() {
    197         if (showsPopup()) {
    198             hidePopup();
    199         }
    200     }
    201 
    202     @Override
    203     public void setOrientation(int degree, boolean animate) {
    204         super.setOrientation(degree, animate);
    205         ViewGroup content = (ViewGroup) mPopup;
    206         if (content == null) return;
    207         for (int i = 0; i < content.getChildCount(); i++) {
    208             RotateImageView iv = (RotateImageView) content.getChildAt(i);
    209             iv.setOrientation(degree, animate);
    210         }
    211     }
    212 
    213     private void updateInitialTranslations() {
    214         if (getResources().getConfiguration().orientation
    215                 == Configuration.ORIENTATION_PORTRAIT) {
    216             mTranslationX = -getWidth() / 2 ;
    217             mTranslationY = getHeight();
    218         } else {
    219             mTranslationX = getWidth();
    220             mTranslationY = getHeight() / 2;
    221         }
    222     }
    223     private void popupAnimationSetup() {
    224         if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
    225             return;
    226         }
    227         updateInitialTranslations();
    228         mPopup.setScaleX(0.3f);
    229         mPopup.setScaleY(0.3f);
    230         mPopup.setTranslationX(mTranslationX);
    231         mPopup.setTranslationY(mTranslationY);
    232         mNeedsAnimationSetup = false;
    233     }
    234 
    235     private boolean animateHidePopup() {
    236         if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
    237             return false;
    238         }
    239         if (mHideAnimationListener == null) {
    240             mHideAnimationListener = new AnimatorListenerAdapter() {
    241                 @Override
    242                 public void onAnimationEnd(Animator animation) {
    243                     // Verify that we weren't canceled
    244                     if (!showsPopup()) {
    245                         mPopup.setVisibility(View.INVISIBLE);
    246                     }
    247                 }
    248             };
    249         }
    250         mPopup.animate()
    251                 .alpha(0f)
    252                 .scaleX(0.3f).scaleY(0.3f)
    253                 .translationX(mTranslationX)
    254                 .translationY(mTranslationY)
    255                 .setDuration(SWITCHER_POPUP_ANIM_DURATION)
    256                 .setListener(mHideAnimationListener);
    257         animate().alpha(1f).setDuration(SWITCHER_POPUP_ANIM_DURATION)
    258                 .setListener(null);
    259         return true;
    260     }
    261 
    262     private boolean animateShowPopup() {
    263         if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
    264             return false;
    265         }
    266         if (mNeedsAnimationSetup) {
    267             popupAnimationSetup();
    268         }
    269         if (mShowAnimationListener == null) {
    270             mShowAnimationListener = new AnimatorListenerAdapter() {
    271                 @Override
    272                 public void onAnimationEnd(Animator animation) {
    273                     // Verify that we weren't canceled
    274                     if (showsPopup()) {
    275                         setVisibility(View.INVISIBLE);
    276                     }
    277                 }
    278             };
    279         }
    280         mPopup.animate()
    281                 .alpha(1f)
    282                 .scaleX(1f).scaleY(1f)
    283                 .translationX(0)
    284                 .translationY(0)
    285                 .setDuration(SWITCHER_POPUP_ANIM_DURATION)
    286                 .setListener(null);
    287         animate().alpha(0f).setDuration(SWITCHER_POPUP_ANIM_DURATION)
    288                 .setListener(mShowAnimationListener);
    289         return true;
    290     }
    291 }
    292