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