CameraActivity.java revision 019cd2a91262707cf4f435f255d433666bc71706
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.Context; 20import android.content.Intent; 21import android.content.res.Configuration; 22import android.graphics.drawable.Drawable; 23import android.os.Bundle; 24import android.provider.MediaStore; 25import android.view.KeyEvent; 26import android.view.LayoutInflater; 27import android.view.MotionEvent; 28import android.view.OrientationEventListener; 29import android.view.View; 30import android.view.View.OnClickListener; 31import android.view.ViewGroup; 32import android.widget.FrameLayout; 33 34import com.android.camera.ui.CameraSwitcher; 35import com.android.camera.ui.RotateImageView; 36import com.android.gallery3d.util.LightCycleHelper; 37 38public class CameraActivity extends ActivityBase 39 implements CameraSwitcher.CameraSwitchListener { 40 public static final int VIDEO_MODULE_INDEX = 0; 41 public static final int PHOTO_MODULE_INDEX = 1; 42 public static final int PANORAMA_MODULE_INDEX = 2; 43 public static final int LIGHTCYCLE_MODULE_INDEX = 3; 44 45 CameraModule mCurrentModule; 46 private FrameLayout mFrame; 47 private ShutterButton mShutter; 48 private RotateImageView mShutterIcon; 49 private RotateImageView mMenu; 50 private CameraSwitcher mSwitcher; 51 private View mShutterSwitcher; 52 private View mBlocker; 53 private Drawable[] mDrawables; 54 private int mCurrentModuleIndex; 55 private MenuListener mMenuListener; 56 private MotionEvent mDown; 57 58 private MyOrientationEventListener mOrientationListener; 59 // The degrees of the device rotated clockwise from its natural orientation. 60 private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; 61 // The orientation compensation for icons. Eg: if the value 62 // is 90, the UI components should be rotated 90 degrees counter-clockwise. 63 private int mOrientationCompensation = 0; 64 65 private static final String TAG = "CAM_activity"; 66 67 private static final int[] DRAW_IDS = { 68 R.drawable.ic_switch_video, 69 R.drawable.ic_switch_camera, 70 R.drawable.ic_switch_pan, 71 com.android.gallery3d.R.drawable.ic_menu_photosphere 72 }; 73 74 public interface MenuListener { 75 public void onMenuClicked(); 76 } 77 78 @Override 79 public void onCreate(Bundle state) { 80 super.onCreate(state); 81 setContentView(R.layout.camera_main); 82 mFrame =(FrameLayout) findViewById(R.id.main_content); 83 mDrawables = new Drawable[DRAW_IDS.length]; 84 for (int i = 0; i < DRAW_IDS.length; i++) { 85 mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]); 86 } 87 init(); 88 mSwitcher.setSwitchListener(this); 89 if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction()) 90 || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) { 91 mCurrentModule = new VideoModule(); 92 mCurrentModuleIndex = VIDEO_MODULE_INDEX; 93 } else { 94 mCurrentModule = new PhotoModule(); 95 mCurrentModuleIndex = PHOTO_MODULE_INDEX; 96 } 97 mCurrentModule.init(this, mFrame, true); 98 mSwitcher.setCurrentIndex(mCurrentModuleIndex); 99 mOrientationListener = new MyOrientationEventListener(this); 100 } 101 102 public void init() { 103 mBlocker = findViewById(R.id.blocker); 104 mShutterSwitcher = findViewById(R.id.camera_shutter_switcher); 105 mShutter = (ShutterButton) findViewById(R.id.shutter_button); 106 mShutterIcon = (RotateImageView) findViewById(R.id.shutter_overlay); 107 mShutterIcon.enableFilter(false); 108 mMenu = (RotateImageView) findViewById(R.id.menu); 109 mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher); 110 mSwitcher.setDrawIds(DRAW_IDS); 111 mMenu.setOnClickListener(new OnClickListener() { 112 @Override 113 public void onClick(View v) { 114 if (mMenuListener != null) { 115 mMenuListener.onMenuClicked(); 116 } 117 } 118 }); 119 int[] drawids = new int[LightCycleHelper.hasLightCycleCapture(this) 120 ? DRAW_IDS.length : DRAW_IDS.length - 1]; 121 int ix = 0; 122 for (int i = 0; i < mDrawables.length; i++) { 123 if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(this)) { 124 continue; // not enabled, so don't add to UI 125 } 126 drawids[ix++] = DRAW_IDS[i]; 127 } 128 mSwitcher.setDrawIds(drawids); 129 } 130 131 public void setMenuListener(MenuListener listener) { 132 mMenuListener = listener; 133 if (mMenu != null) { 134 mMenu.setVisibility((listener != null) ? View.VISIBLE : View.GONE); 135 } 136 } 137 138 private class MyOrientationEventListener 139 extends OrientationEventListener { 140 public MyOrientationEventListener(Context context) { 141 super(context); 142 } 143 144 @Override 145 public void onOrientationChanged(int orientation) { 146 // We keep the last known orientation. So if the user first orient 147 // the camera then point the camera to floor or sky, we still have 148 // the correct orientation. 149 if (orientation == ORIENTATION_UNKNOWN) return; 150 mOrientation = Util.roundOrientation(orientation, mOrientation); 151 // When the screen is unlocked, display rotation may change. Always 152 // calculate the up-to-date orientationCompensation. 153 int orientationCompensation = 154 (mOrientation + Util.getDisplayRotation(CameraActivity.this)) % 360; 155 // Rotate camera mode icons in the switcher 156 if (mOrientationCompensation != orientationCompensation) { 157 mOrientationCompensation = orientationCompensation; 158 if (mSwitcher != null) { 159 mSwitcher.setOrientation(mOrientationCompensation, true); 160 } 161 if (mMenu != null) { 162 mMenu.setOrientation(mOrientationCompensation, true); 163 } 164 } 165 mCurrentModule.onOrientationChanged(orientation); 166 } 167 } 168 169 @Override 170 public void onCameraSelected(int i) { 171 if (i != mCurrentModuleIndex) { 172 mPaused = true; 173 boolean wasPanorama = isPanoramaActivity(); 174 closeModule(mCurrentModule); 175 mCurrentModuleIndex = i; 176 mMenuListener = null; 177 switch (i) { 178 case VIDEO_MODULE_INDEX: 179 mCurrentModule = new VideoModule(); 180 break; 181 case PHOTO_MODULE_INDEX: 182 mCurrentModule = new PhotoModule(); 183 break; 184 case PANORAMA_MODULE_INDEX: 185 mCurrentModule = new PanoramaModule(); 186 break; 187 case LIGHTCYCLE_MODULE_INDEX: 188 mCurrentModule = LightCycleHelper.createPanoramaModule(); 189 break; 190 } 191 openModule(mCurrentModule, wasPanorama); 192 mCurrentModule.onOrientationChanged(mOrientation); 193 } 194 } 195 196 private void openModule(CameraModule module, boolean wasPanorama) { 197 module.init(this, mFrame, !(wasPanorama || isPanoramaActivity())); 198 mPaused = false; 199 module.onResumeBeforeSuper(); 200 module.onResumeAfterSuper(); 201 } 202 203 private void closeModule(CameraModule module) { 204 module.onPauseBeforeSuper(); 205 module.onPauseAfterSuper(); 206 mFrame.removeAllViews(); 207 } 208 209 private void showShutterIcon(boolean show) { 210 showShutterIcon(show, DRAW_IDS[mCurrentModuleIndex]); 211 } 212 213 private void showShutterIcon(boolean show, int resid) { 214 if (show) { 215 mShutterIcon.setImageResource(resid); 216 mShutterIcon.setOrientation(mOrientationCompensation, false); 217 } 218 mShutterIcon.setVisibility(show ? View.VISIBLE : View.GONE); 219 } 220 221 public ShutterButton getShutterButton() { 222 return mShutter; 223 } 224 225 public void hideUI() { 226 hideSwitcher(); 227 mShutter.setVisibility(View.GONE); 228 mShutterIcon.setVisibility(View.GONE); 229 } 230 231 public void showUI() { 232 showSwitcher(); 233 mShutter.setVisibility(View.VISIBLE); 234 } 235 236 // hide the switcher and show the given shutter icon 237 public void hideSwitcher(int resid) { 238 mSwitcher.setVisibility(View.GONE); 239 mMenu.setVisibility(View.GONE); 240 mBlocker.setVisibility(View.GONE); 241 showShutterIcon(true, resid); 242 } 243 244 public void hideSwitcher() { 245 mSwitcher.setVisibility(View.GONE); 246 mMenu.setVisibility(View.GONE); 247 mBlocker.setVisibility(View.GONE); 248 showShutterIcon(true); 249 } 250 251 public void showSwitcher() { 252 if (mCurrentModule.needsSwitcher()) { 253 mSwitcher.setVisibility(View.VISIBLE); 254 mBlocker.setVisibility(View.VISIBLE); 255 if (mMenuListener != null) { 256 mMenu.setVisibility(View.VISIBLE); 257 } 258 showShutterIcon(false); 259 } 260 } 261 262 @Override 263 public void onConfigurationChanged(Configuration config) { 264 super.onConfigurationChanged(config); 265 266 ViewGroup appRoot = (ViewGroup) findViewById(R.id.content); 267 // remove old switcher, shutter and shutter icon 268 View cameraControlsView = findViewById(R.id.camera_shutter_switcher); 269 appRoot.removeView(cameraControlsView); 270 271 // create new layout with the current orientation 272 LayoutInflater inflater = getLayoutInflater(); 273 inflater.inflate(R.layout.camera_shutter_switcher, appRoot); 274 init(); 275 276 mSwitcher.setImageResource(DRAW_IDS[mCurrentModuleIndex]); 277 mSwitcher.setSwitchListener(this); 278 if (mShowCameraAppView) { 279 showUI(); 280 } else { 281 hideUI(); 282 } 283 mCurrentModule.onConfigurationChanged(config); 284 } 285 286 @Override 287 public void onPause() { 288 mPaused = true; 289 mOrientationListener.disable(); 290 mCurrentModule.onPauseBeforeSuper(); 291 super.onPause(); 292 mCurrentModule.onPauseAfterSuper(); 293 } 294 295 @Override 296 public void onResume() { 297 mPaused = false; 298 mOrientationListener.enable(); 299 mCurrentModule.onResumeBeforeSuper(); 300 super.onResume(); 301 mCurrentModule.onResumeAfterSuper(); 302 } 303 304 @Override 305 protected void onFullScreenChanged(boolean full) { 306 if (full) { 307 showUI(); 308 } else { 309 hideUI(); 310 } 311 super.onFullScreenChanged(full); 312 mCurrentModule.onFullScreenChanged(full); 313 } 314 315 @Override 316 protected void onStop() { 317 super.onStop(); 318 mCurrentModule.onStop(); 319 } 320 321 @Override 322 protected void onNewIntent(Intent intent) { 323 super.onNewIntent(intent); 324 getStateManager().clearActivityResult(); 325 } 326 327 @Override 328 protected void installIntentFilter() { 329 super.installIntentFilter(); 330 mCurrentModule.installIntentFilter(); 331 } 332 333 @Override 334 protected void onActivityResult( 335 int requestCode, int resultCode, Intent data) { 336 super.onActivityResult(requestCode, resultCode, data); 337 mCurrentModule.onActivityResult(requestCode, resultCode, data); 338 } 339 340 // Preview area is touched. Handle touch focus. 341 @Override 342 protected void onSingleTapUp(View view, int x, int y) { 343 mCurrentModule.onSingleTapUp(view, x, y); 344 } 345 346 @Override 347 public void onBackPressed() { 348 if (!mCurrentModule.onBackPressed()) { 349 super.onBackPressed(); 350 } 351 } 352 353 @Override 354 public boolean onKeyDown(int keyCode, KeyEvent event) { 355 return mCurrentModule.onKeyDown(keyCode, event) 356 || super.onKeyDown(keyCode, event); 357 } 358 359 @Override 360 public boolean onKeyUp(int keyCode, KeyEvent event) { 361 return mCurrentModule.onKeyUp(keyCode, event) 362 || super.onKeyUp(keyCode, event); 363 } 364 365 public void cancelActivityTouchHandling() { 366 if (mDown != null) { 367 MotionEvent cancel = MotionEvent.obtain(mDown); 368 cancel.setAction(MotionEvent.ACTION_CANCEL); 369 super.dispatchTouchEvent(cancel); 370 } 371 } 372 373 @Override 374 public boolean dispatchTouchEvent(MotionEvent m) { 375 if (m.getActionMasked() == MotionEvent.ACTION_DOWN) { 376 mDown = m; 377 } 378 if ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) { 379 return mSwitcher.onTouch(null, m); 380 } else { 381 return mShutterSwitcher.dispatchTouchEvent(m) 382 || mCurrentModule.dispatchTouchEvent(m); 383 } 384 } 385 386 public boolean superDispatchTouchEvent(MotionEvent m) { 387 return super.dispatchTouchEvent(m); 388 } 389 390 // Preview texture has been copied. Now camera can be released and the 391 // animation can be started. 392 @Override 393 public void onPreviewTextureCopied() { 394 mCurrentModule.onPreviewTextureCopied(); 395 } 396 397 @Override 398 public void onUserInteraction() { 399 super.onUserInteraction(); 400 mCurrentModule.onUserInteraction(); 401 } 402 403 @Override 404 protected boolean updateStorageHintOnResume() { 405 return mCurrentModule.updateStorageHintOnResume(); 406 } 407 408 @Override 409 public void updateCameraAppView() { 410 super.updateCameraAppView(); 411 mCurrentModule.updateCameraAppView(); 412 } 413 414 @Override 415 public boolean isPanoramaActivity() { 416 return (mCurrentModule instanceof PanoramaModule); 417 } 418} 419