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