CameraSwitcher.java revision b8317ef78fa41224a0a8d43431c3eac8e10772f1
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
17package com.android.camera.ui;
18
19import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.AnimatorListenerAdapter;
22import android.content.Context;
23import android.content.res.Configuration;
24import android.graphics.Canvas;
25import android.graphics.drawable.Drawable;
26import android.util.AttributeSet;
27import android.view.LayoutInflater;
28import android.view.MotionEvent;
29import android.view.View;
30import android.view.View.OnClickListener;
31import android.view.View.OnTouchListener;
32import android.view.ViewGroup;
33import android.widget.LinearLayout;
34
35import com.android.camera.R;
36import com.android.gallery3d.common.ApiHelper;
37
38public 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