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