CameraSwitcher.java revision d9a36946b24f4ccd697aa0139aa978c962eb95e1
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.util.AttributeSet;
24import android.view.LayoutInflater;
25import android.view.MotionEvent;
26import android.view.View;
27import android.view.View.OnClickListener;
28import android.view.View.OnTouchListener;
29import android.view.ViewGroup;
30import android.widget.LinearLayout;
31
32import com.android.camera.R;
33import com.android.gallery3d.common.ApiHelper;
34
35public class CameraSwitcher extends RotateImageView
36        implements OnClickListener, OnTouchListener {
37
38    private static final String TAG = "CAM_Switcher";
39
40    public interface CameraSwitchListener {
41
42        public void onCameraSelected(int i);
43    }
44
45    private CameraSwitchListener mListener;
46    private int mCurrentIndex;
47    private int[] mDrawIds;
48    private int mItemSize;
49    private View mPopup;
50    private View mParent;
51    private boolean mShowingPopup;
52    private boolean mNeedsAnimationSetup;
53
54    private AnimatorListener mHideAnimationListener;
55    private AnimatorListener mShowAnimationListener;
56
57    public CameraSwitcher(Context context) {
58        super(context);
59        init(context);
60    }
61
62    public CameraSwitcher(Context context, AttributeSet attrs) {
63        super(context, attrs);
64        init(context);
65    }
66
67    private void init(Context context) {
68        mItemSize = context.getResources().getDimensionPixelSize(R.dimen.switcher_size);
69        setOnClickListener(this);
70    }
71
72    public void setDrawIds(int[] drawids) {
73        mDrawIds = drawids;
74    }
75
76    public void setCurrentIndex(int i) {
77        mCurrentIndex = i;
78        setImageResource(mDrawIds[i]);
79    }
80
81    public void setSwitchListener(CameraSwitchListener l) {
82        mListener = l;
83    }
84
85    @Override
86    public void onClick(View v) {
87        showSwitcher();
88    }
89
90    private void onCameraSelected(int ix) {
91        hidePopup();
92        if ((ix != mCurrentIndex) && (mListener != null)) {
93            setCurrentIndex(ix);
94            mListener.onCameraSelected(ix);
95        }
96    }
97
98    private void initPopup() {
99        mParent = LayoutInflater.from(getContext()).inflate(R.layout.switcher_popup,
100                (ViewGroup) getParent());
101        LinearLayout content = (LinearLayout) mParent.findViewById(R.id.content);
102        mPopup = content;
103        mPopup.setVisibility(View.INVISIBLE);
104        mNeedsAnimationSetup = true;
105        for (int i = mDrawIds.length - 1; i >= 0; i--) {
106            RotateImageView item = new RotateImageView(getContext());
107            item.setImageResource(mDrawIds[i]);
108            item.setBackgroundResource(R.drawable.bg_pressed);
109            final int index = i;
110            item.setOnClickListener(new OnClickListener() {
111                @Override
112                public void onClick(View v) {
113                    onCameraSelected(index);
114                }
115            });
116            switch (mDrawIds[i]) {
117                case R.drawable.ic_switch_camera:
118                    item.setContentDescription(getContext().getResources().getString(
119                            R.string.accessibility_switch_to_camera));
120                    break;
121                case R.drawable.ic_switch_video:
122                    item.setContentDescription(getContext().getResources().getString(
123                            R.string.accessibility_switch_to_video));
124                    break;
125                case R.drawable.ic_switch_pan:
126                    item.setContentDescription(getContext().getResources().getString(
127                            R.string.accessibility_switch_to_panorama));
128                    break;
129                case com.android.gallery3d.R.drawable.ic_menu_photosphere:
130                    item.setContentDescription(getContext().getResources().getString(
131                            R.string.accessibility_switch_to_lightcycle));
132                    break;
133                default:
134                    break;
135            }
136            content.addView(item, new LinearLayout.LayoutParams(mItemSize, mItemSize));
137        }
138    }
139
140    public boolean showsPopup() {
141        return mShowingPopup;
142    }
143
144    public boolean isInsidePopup(MotionEvent evt) {
145        if (!showsPopup()) return false;
146        return evt.getX() >= mPopup.getLeft()
147                && evt.getX() < mPopup.getRight()
148                && evt.getY() >= mPopup.getTop()
149                && evt.getY() < mPopup.getBottom();
150    }
151
152    private void hidePopup() {
153        mShowingPopup = false;
154        setVisibility(View.VISIBLE);
155        if (mPopup != null && !animateHidePopup()) {
156            mPopup.setVisibility(View.INVISIBLE);
157        }
158        mParent.setOnTouchListener(null);
159    }
160
161    private void showSwitcher() {
162        mShowingPopup = true;
163        if (mPopup == null) {
164            initPopup();
165        }
166        mPopup.setVisibility(View.VISIBLE);
167        if (!animateShowPopup()) {
168            setVisibility(View.INVISIBLE);
169        }
170        mParent.setOnTouchListener(this);
171    }
172
173    @Override
174    public boolean onTouch(View v, MotionEvent event) {
175        if (showsPopup()) {
176            hidePopup();
177        }
178        return true;
179    }
180
181    @Override
182    public void setOrientation(int degree, boolean animate) {
183        super.setOrientation(degree, animate);
184        ViewGroup content = (ViewGroup) mPopup;
185        if (content == null) return;
186        for (int i = 0; i < content.getChildCount(); i++) {
187            RotateImageView iv = (RotateImageView) content.getChildAt(i);
188            iv.setOrientation(degree, animate);
189        }
190    }
191
192    private void popupAnimationSetup() {
193        if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
194            return;
195        }
196        mPopup.setScaleX(0.3f);
197        mPopup.setScaleY(0.3f);
198        mPopup.setTranslationX(-getWidth() / 2);
199        mPopup.setTranslationY(getHeight());
200        mNeedsAnimationSetup = false;
201    }
202
203    private boolean animateHidePopup() {
204        if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
205            return false;
206        }
207        if (mHideAnimationListener == null) {
208            mHideAnimationListener = new AnimatorListenerAdapter() {
209                @Override
210                public void onAnimationEnd(Animator animation) {
211                    // Verify that we weren't canceled
212                    if (!showsPopup()) {
213                        mPopup.setVisibility(View.INVISIBLE);
214                    }
215                }
216            };
217        }
218        mPopup.animate()
219                .alpha(0f)
220                .scaleX(0.3f).scaleY(0.3f)
221                .translationX(-getWidth() / 2)
222                .translationY(getHeight())
223                .setListener(mHideAnimationListener);
224        animate().alpha(1f).setListener(null);
225        return true;
226    }
227
228    private boolean animateShowPopup() {
229        if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) {
230            return false;
231        }
232        if (mNeedsAnimationSetup) {
233            popupAnimationSetup();
234        }
235        if (mShowAnimationListener == null) {
236            mShowAnimationListener = new AnimatorListenerAdapter() {
237                @Override
238                public void onAnimationEnd(Animator animation) {
239                    // Verify that we weren't canceled
240                    if (showsPopup()) {
241                        setVisibility(View.INVISIBLE);
242                    }
243                }
244            };
245        }
246        mPopup.animate()
247                .alpha(1f)
248                .scaleX(1f).scaleY(1f)
249                .translationX(0)
250                .translationY(0)
251                .setListener(null);
252        animate().alpha(0f)
253                .setListener(mShowAnimationListener);
254        return true;
255    }
256}
257