CameraActivity.java revision 9f8b479c44e8fafda688ac0fab9882584a94d55f
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;
18
19import android.content.Intent;
20import android.content.res.Configuration;
21import android.graphics.drawable.Drawable;
22import android.os.Bundle;
23import android.provider.MediaStore;
24import android.util.Log;
25import android.view.KeyEvent;
26import android.view.MotionEvent;
27import android.view.View;
28import android.view.View.OnClickListener;
29import android.view.ViewConfiguration;
30import android.view.ViewGroup.LayoutParams;
31import android.widget.FrameLayout;
32import android.widget.ImageView;
33
34import com.android.camera.ui.CameraSwitcher;
35import com.android.gallery3d.util.LightCycleHelper;
36
37import java.util.HashSet;
38
39public class CameraActivity extends ActivityBase
40        implements CameraSwitcher.CameraSwitchListener {
41    public static final int VIDEO_MODULE_INDEX = 0;
42    public static final int PHOTO_MODULE_INDEX = 1;
43    public static final int PANORAMA_MODULE_INDEX = 2;
44    public static final int LIGHTCYCLE_MODULE_INDEX = 3;
45
46    CameraModule mCurrentModule;
47    private FrameLayout mFrame;
48    private ShutterButton mShutter;
49    private CameraSwitcher mSwitcher;
50    private Drawable[] mDrawables;
51    private int mSelectedModule;
52    private HashSet<View> mDispatched;
53    private Dispatcher mDispatcher;
54
55    private static final String TAG = "CAM_activity";
56
57    private static final int[] DRAW_IDS = {
58            R.drawable.ic_switch_video_holo_light,
59            R.drawable.ic_switch_camera_holo_light,
60            R.drawable.ic_switch_pan_holo_light,
61            R.drawable.ic_switch_photo_pan_holo_light
62    };
63
64    @Override
65    public void onCreate(Bundle state) {
66        super.onCreate(state);
67        mDispatched = new HashSet<View>();
68        mDispatcher = new Dispatcher();
69        setContentView(R.layout.camera_main);
70        mFrame =(FrameLayout) findViewById(R.id.main_content);
71        mShutter = (ShutterButton) findViewById(R.id.shutter_button);
72        mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher);
73        mDrawables = new Drawable[DRAW_IDS.length];
74        for (int i = 0; i < DRAW_IDS.length; i++) {
75            Drawable d = getResources().getDrawable(DRAW_IDS[i]);
76            mDrawables[i] = d;
77        }
78        for (int i = 0; i < mDrawables.length; i++) {
79            if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(this)) {
80                continue; // not enabled, so don't add to UI
81            }
82            ImageView iv = new ImageView(this);
83            iv.setImageDrawable(mDrawables[i]);
84            mSwitcher.add(iv, new LayoutParams(LayoutParams.WRAP_CONTENT,
85                    LayoutParams.WRAP_CONTENT));
86            final int index = i;
87            iv.setOnClickListener(new OnClickListener() {
88                @Override
89                public void onClick(View arg0) {
90                    mSwitcher.setCurrentModule(index);
91                    onCameraSelected(index);
92                }
93            });
94        }
95
96        mSwitcher.setSwitchListener(this);
97        if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction())
98                || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) {
99            mCurrentModule = new VideoModule();
100            mSelectedModule = VIDEO_MODULE_INDEX;
101        } else {
102            mCurrentModule = new PhotoModule();
103            mSelectedModule = PHOTO_MODULE_INDEX;
104        }
105        mCurrentModule.init(this, mFrame, true);
106        mSwitcher.setCurrentModule(mSelectedModule);
107    }
108
109    @Override
110    public void onScroll() {
111    }
112
113    @Override
114    public void onCameraSelected(int i) {
115        if (i != mSelectedModule) {
116            mPaused = true;
117            boolean wasPanorama = isPanoramaActivity();
118            closeModule(mCurrentModule);
119            mSelectedModule = i;
120            switch (i) {
121                case VIDEO_MODULE_INDEX:
122                    mCurrentModule = new VideoModule();
123                    break;
124                case PHOTO_MODULE_INDEX:
125                    mCurrentModule = new PhotoModule();
126                    break;
127                case PANORAMA_MODULE_INDEX:
128                    mCurrentModule = new PanoramaModule();
129                    break;
130                case LIGHTCYCLE_MODULE_INDEX:
131                    mCurrentModule = LightCycleHelper.createPanoramaModule();
132                    break;
133            }
134            openModule(mCurrentModule, wasPanorama);
135        }
136    }
137
138    private void openModule(CameraModule module, boolean wasPanorama) {
139        module.init(this, mFrame, !(wasPanorama || isPanoramaActivity()));
140        mPaused = false;
141        module.onResumeBeforeSuper();
142        module.onResumeAfterSuper();
143    }
144
145    private void closeModule(CameraModule module) {
146        module.onPauseBeforeSuper();
147        module.onPauseAfterSuper();
148        mFrame.removeAllViews();
149    }
150
151    public ShutterButton getShutterButton() {
152        return mShutter;
153    }
154
155    public void hideUI() {
156        hideSwitcher();
157        mShutter.setVisibility(View.GONE);
158    }
159
160    public void showUI() {
161        showSwitcher();
162        mShutter.setVisibility(View.VISIBLE);
163    }
164
165    public void hideSwitcher() {
166        mSwitcher.setVisibility(View.GONE);
167    }
168
169    public void showSwitcher() {
170        if (mCurrentModule.needsSwitcher()) {
171            mSwitcher.setVisibility(View.VISIBLE);
172        }
173    }
174
175    public void switchToModule(int moduleIndex) {
176        mSwitcher.setCurrentModule(moduleIndex);
177        onCameraSelected(moduleIndex);
178    }
179
180    @Override
181    public void onConfigurationChanged(Configuration config) {
182        super.onConfigurationChanged(config);
183        mCurrentModule.onConfigurationChanged(config);
184    }
185
186    @Override
187    public void onPause() {
188        mPaused = true;
189        mCurrentModule.onPauseBeforeSuper();
190        super.onPause();
191        mCurrentModule.onPauseAfterSuper();
192    }
193
194    @Override
195    public void onResume() {
196        mPaused = false;
197        mCurrentModule.onResumeBeforeSuper();
198        super.onResume();
199        mCurrentModule.onResumeAfterSuper();
200    }
201
202    @Override
203    protected void onFullScreenChanged(boolean full) {
204        if (full) {
205            showUI();
206        } else {
207            hideUI();
208        }
209        super.onFullScreenChanged(full);
210        mCurrentModule.onFullScreenChanged(full);
211    }
212
213    @Override
214    protected void onStop() {
215        super.onStop();
216        mCurrentModule.onStop();
217    }
218
219    @Override
220    protected void onNewIntent(Intent intent) {
221        super.onNewIntent(intent);
222        getStateManager().clearActivityResult();
223    }
224
225    @Override
226    protected void installIntentFilter() {
227        super.installIntentFilter();
228        mCurrentModule.installIntentFilter();
229    }
230
231    @Override
232    protected void onActivityResult(
233            int requestCode, int resultCode, Intent data) {
234        super.onActivityResult(requestCode, resultCode, data);
235        mCurrentModule.onActivityResult(requestCode, resultCode, data);
236    }
237
238    // Preview area is touched. Handle touch focus.
239    @Override
240    protected void onSingleTapUp(View view, int x, int y) {
241        mCurrentModule.onSingleTapUp(view, x, y);
242    }
243
244    @Override
245    public void onBackPressed() {
246        if (!mCurrentModule.onBackPressed()) {
247            super.onBackPressed();
248        }
249    }
250
251    @Override
252    public boolean onKeyDown(int keyCode, KeyEvent event) {
253        return mCurrentModule.onKeyDown(keyCode,  event)
254                || super.onKeyDown(keyCode, event);
255    }
256
257    @Override
258    public boolean onKeyUp(int keyCode, KeyEvent event) {
259        return mCurrentModule.onKeyUp(keyCode,  event)
260                || super.onKeyUp(keyCode, event);
261    }
262
263    public void cancelActivityTouchHandling() {
264        MotionEvent e = mDispatcher.getCancelEvent();
265        if (e != null) {
266            super.dispatchTouchEvent(e);
267        }
268    }
269
270    @Override
271    public boolean dispatchTouchEvent(MotionEvent m) {
272        boolean handled = false;
273        if ((m.getActionMasked() == MotionEvent.ACTION_DOWN) || mDispatcher.isActive()) {
274            mShutter.enableTouch(true);
275            mSwitcher.enableTouch(true);
276            handled = mDispatcher.dispatchTouchEvent(m);
277            mShutter.enableTouch(false);
278            mSwitcher.enableTouch(false);
279        }
280        if (!handled) {
281            handled = mCurrentModule.dispatchTouchEvent(m);
282        }
283        return handled || super.dispatchTouchEvent(m);
284    }
285
286    private boolean isInside(MotionEvent evt, View v) {
287        return (v.getVisibility() == View.VISIBLE
288                && evt.getX() >= v.getLeft() && evt.getX() < v.getRight()
289                && evt.getY() >= v.getTop() && evt.getY() < v.getBottom());
290    }
291
292    private MotionEvent transformEvent(MotionEvent m, View v) {
293        MotionEvent r = MotionEvent.obtain(m);
294        r.offsetLocation(- v.getLeft(), - v.getTop());
295        return r;
296    }
297
298
299    // Preview texture has been copied. Now camera can be released and the
300    // animation can be started.
301    @Override
302    public void onPreviewTextureCopied() {
303        mCurrentModule.onPreviewTextureCopied();
304    }
305
306    @Override
307    public void onUserInteraction() {
308        super.onUserInteraction();
309        mCurrentModule.onUserInteraction();
310    }
311
312    @Override
313    protected boolean updateStorageHintOnResume() {
314        return mCurrentModule.updateStorageHintOnResume();
315    }
316
317    @Override
318    public void updateCameraAppView() {
319        super.updateCameraAppView();
320        mCurrentModule.updateCameraAppView();
321    }
322
323    @Override
324    public boolean isPanoramaActivity() {
325        return (mCurrentModule instanceof PanoramaModule);
326    }
327
328    private class Dispatcher {
329
330        private boolean mActive;
331        private MotionEvent mDown;
332        private int mSlop;
333        private boolean mDownInShutter;
334
335        public Dispatcher() {
336            mSlop = ViewConfiguration.get(CameraActivity.this).getScaledTouchSlop();
337            mActive = true;
338        }
339
340        public MotionEvent getCancelEvent() {
341            if (mDown != null) {
342                MotionEvent cancel = MotionEvent.obtain(mDown);
343                cancel.setAction(MotionEvent.ACTION_CANCEL);
344                return cancel;
345            }
346            return null;
347        }
348
349        public boolean isActive() {
350            return mActive;
351        }
352
353        public boolean dispatchTouchEvent(MotionEvent m) {
354            switch (m.getActionMasked()) {
355            case MotionEvent.ACTION_DOWN:
356                mActive = false;
357                mDownInShutter = isInside(m, mShutter);
358                mDown = m;
359                if (mDownInShutter) {
360                    sendTo(m, mShutter);
361                    mActive = true;
362                }
363                if (isInside(m, mSwitcher)) {
364                    sendTo(m, mSwitcher);
365                    mActive = true;
366                }
367                break;
368            case MotionEvent.ACTION_MOVE:
369                if (mDownInShutter) {
370                    if (Math.abs(m.getX() - mDown.getX()) > mSlop) {
371                        // sliding switcher
372                        mDownInShutter = false;
373                        MotionEvent cancel = MotionEvent.obtain(m);
374                        cancel.setAction(MotionEvent.ACTION_CANCEL);
375                        sendTo(cancel, mShutter);
376                        sendTo(m, mSwitcher);
377                    } else {
378                        sendTo(m, mShutter);
379                        sendTo(m, mSwitcher);
380                    }
381                } else {
382                    sendTo(m, mSwitcher);
383                }
384                break;
385            case MotionEvent.ACTION_UP:
386                if (mDownInShutter) {
387                    sendTo(m, mShutter);
388                    MotionEvent cancel = MotionEvent.obtain(m);
389                    cancel.setAction(MotionEvent.ACTION_CANCEL);
390                    sendTo(cancel, mSwitcher);
391                } else {
392                    sendTo(m, mSwitcher);
393                }
394                break;
395            case MotionEvent.ACTION_CANCEL:
396                if (mDownInShutter) {
397                    sendTo(m, mShutter);
398                }
399                sendTo(m, mSwitcher);
400                break;
401            }
402            return mActive;
403        }
404    }
405
406    private boolean sendTo(MotionEvent m, View v) {
407        return v.dispatchTouchEvent(transformEvent(m, v));
408    }
409
410}
411