PhotoUI.java revision fd2e619a2fb263315816b3579a9c6751c398132d
1/* 2 * Copyright (C) 2013 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 17 18package com.android.camera; 19 20import android.hardware.Camera; 21import android.hardware.Camera.Face; 22import android.hardware.Camera.FaceDetectionListener; 23import android.hardware.Camera.Parameters; 24import android.util.Log; 25import android.view.Gravity; 26import android.view.MotionEvent; 27import android.view.SurfaceHolder; 28import android.view.View; 29import android.view.View.OnClickListener; 30import android.view.View.OnLayoutChangeListener; 31import android.view.ViewGroup; 32import android.view.ViewStub; 33import android.widget.FrameLayout; 34import android.widget.FrameLayout.LayoutParams; 35import android.widget.ImageView; 36import android.widget.Toast; 37 38import com.android.camera.CameraPreference.OnPreferenceChangedListener; 39import com.android.camera.FocusOverlayManager.FocusUI; 40import com.android.camera.ui.AbstractSettingPopup; 41import com.android.camera.ui.CountDownView; 42import com.android.camera.ui.CountDownView.OnCountDownFinishedListener; 43import com.android.camera.ui.FaceView; 44import com.android.camera.ui.FocusIndicator; 45import com.android.camera.ui.PieRenderer; 46import com.android.camera.ui.PieRenderer.PieListener; 47import com.android.camera.ui.RenderOverlay; 48import com.android.camera.ui.ZoomRenderer; 49import com.android.gallery3d.R; 50import com.android.gallery3d.common.ApiHelper; 51 52import java.util.List; 53 54public class PhotoUI implements PieListener, 55 SurfaceHolder.Callback, 56 PreviewGestures.SingleTapListener, 57 FocusUI, 58 LocationManager.Listener, 59 FaceDetectionListener, 60 PreviewGestures.SwipeListener { 61 62 private static final String TAG = "CAM_UI"; 63 64 private CameraActivity mActivity; 65 private PhotoController mController; 66 private PreviewGestures mGestures; 67 68 private View mRootView; 69 private Object mSurfaceTexture; 70 private volatile SurfaceHolder mSurfaceHolder; 71 72 private AbstractSettingPopup mPopup; 73 private ShutterButton mShutterButton; 74 private CountDownView mCountDownView; 75 76 private FaceView mFaceView; 77 private RenderOverlay mRenderOverlay; 78 private View mReviewCancelButton; 79 private View mReviewDoneButton; 80 private View mReviewRetakeButton; 81 82 private View mMenuButton; 83 private View mBlocker; 84 private PhotoMenu mMenu; 85 86 // Small indicators which show the camera settings in the viewfinder. 87 private ImageView mExposureIndicator; 88 private ImageView mFlashIndicator; 89 private ImageView mSceneIndicator; 90 private ImageView mHdrIndicator; 91 // A view group that contains all the small indicators. 92 private View mOnScreenIndicators; 93 94 private PieRenderer mPieRenderer; 95 private ZoomRenderer mZoomRenderer; 96 private Toast mNotSelectableToast; 97 98 private int mZoomMax; 99 private List<Integer> mZoomRatios; 100 101 private int mPreviewWidth = 0; 102 private int mPreviewHeight = 0; 103 104 private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() { 105 @Override 106 public void onLayoutChange(View v, int left, int top, int right, 107 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 108 int width = right - left; 109 int height = bottom - top; 110 // Full-screen screennail 111 int w = width; 112 int h = height; 113 if (Util.getDisplayRotation(mActivity) % 180 != 0) { 114 w = height; 115 h = width; 116 } 117 if (mPreviewWidth != w || mPreviewHeight != h) { 118 mPreviewWidth = w; 119 mPreviewHeight = h; 120 mController.onScreenSizeChanged(width, height, w, h); 121 } 122 } 123 }; 124 125 public PhotoUI(CameraActivity activity, PhotoController controller, View parent) { 126 mActivity = activity; 127 mController = controller; 128 mRootView = parent; 129 130 mActivity.getLayoutInflater().inflate(R.layout.photo_module, 131 (ViewGroup) mRootView, true); 132 mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay); 133 134 initIndicators(); 135 mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture)); 136 mCountDownView.setCountDownFinishedListener((OnCountDownFinishedListener) mController); 137 138 if (ApiHelper.HAS_FACE_DETECTION) { 139 ViewStub faceViewStub = (ViewStub) mRootView 140 .findViewById(R.id.face_view_stub); 141 if (faceViewStub != null) { 142 faceViewStub.inflate(); 143 mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); 144 } 145 } 146 147 } 148 149 public View getRootView() { 150 return mRootView; 151 } 152 153 private void initIndicators() { 154 mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators); 155 mExposureIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_exposure_indicator); 156 mFlashIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_flash_indicator); 157 mSceneIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_scenemode_indicator); 158 mHdrIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_hdr_indicator); 159 } 160 161 public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs, 162 Camera.Parameters params, OnPreferenceChangedListener listener) { 163 if (mPieRenderer == null) { 164 mPieRenderer = new PieRenderer(mActivity); 165 mPieRenderer.setPieListener(this); 166 mRenderOverlay.addRenderer(mPieRenderer); 167 } 168 if (mMenu == null) { 169 mMenu = new PhotoMenu(mActivity, this, mPieRenderer); 170 mMenu.setListener(listener); 171 } 172 mMenu.initialize(prefGroup); 173 174 if (mZoomRenderer == null) { 175 mZoomRenderer = new ZoomRenderer(mActivity); 176 mRenderOverlay.addRenderer(mZoomRenderer); 177 } 178 if (mGestures == null) { 179 // this will handle gesture disambiguation and dispatching 180 mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer, 181 this); 182 } 183 mGestures.reset(); 184 mGestures.setRenderOverlay(mRenderOverlay); 185 mGestures.addTouchReceiver(mMenuButton); 186 mGestures.addUnclickableArea(mBlocker); 187 // make sure to add touch targets for image capture 188 if (mController.isImageCaptureIntent()) { 189 if (mReviewCancelButton != null) { 190 mGestures.addTouchReceiver(mReviewCancelButton); 191 } 192 if (mReviewDoneButton != null) { 193 mGestures.addTouchReceiver(mReviewDoneButton); 194 } 195 } 196 mRenderOverlay.requestLayout(); 197 198 initializeZoom(params); 199 updateOnScreenIndicators(params, prefs); 200 } 201 202 private void openMenu() { 203 if (mPieRenderer != null) { 204 // If autofocus is not finished, cancel autofocus so that the 205 // subsequent touch can be handled by PreviewGestures 206 if (mController.getCameraState() == PhotoController.FOCUSING) { 207 mController.cancelAutoFocus(); 208 } 209 mPieRenderer.showInCenter(); 210 } 211 } 212 213 public void initializeControlByIntent() { 214 mBlocker = mActivity.findViewById(R.id.blocker); 215 mMenuButton = mActivity.findViewById(R.id.menu); 216 mMenuButton.setOnClickListener(new OnClickListener() { 217 @Override 218 public void onClick(View v) { 219 openMenu(); 220 } 221 }); 222 if (mController.isImageCaptureIntent()) { 223 mActivity.hideSwitcher(); 224 ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls); 225 mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls); 226 227 mReviewDoneButton = mActivity.findViewById(R.id.btn_done); 228 mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); 229 mReviewRetakeButton = mActivity.findViewById(R.id.btn_retake); 230 mReviewCancelButton.setVisibility(View.VISIBLE); 231 232 mReviewDoneButton.setOnClickListener(new OnClickListener() { 233 @Override 234 public void onClick(View v) { 235 mController.onCaptureDone(); 236 } 237 }); 238 mReviewCancelButton.setOnClickListener(new OnClickListener() { 239 @Override 240 public void onClick(View v) { 241 mController.onCaptureCancelled(); 242 } 243 }); 244 245 mReviewRetakeButton.setOnClickListener(new OnClickListener() { 246 @Override 247 public void onClick(View v) { 248 mController.onCaptureRetake(); 249 } 250 }); 251 } 252 } 253 254 // called from onResume but only the first time 255 public void initializeFirstTime() { 256 // Initialize shutter button. 257 mShutterButton = mActivity.getShutterButton(); 258 mShutterButton.setImageResource(R.drawable.btn_new_shutter); 259 mShutterButton.setOnShutterButtonListener(mController); 260 mShutterButton.setVisibility(View.VISIBLE); 261 mRootView.addOnLayoutChangeListener(mLayoutListener); 262 } 263 264 // called from onResume every other time 265 public void initializeSecondTime(Camera.Parameters params) { 266 initializeZoom(params); 267 if (mController.isImageCaptureIntent()) { 268 hidePostCaptureAlert(); 269 } 270 if (mMenu != null) { 271 mMenu.reloadPreferences(); 272 } 273 mRootView.addOnLayoutChangeListener(mLayoutListener); 274 } 275 276 public void initializeZoom(Camera.Parameters params) { 277 if ((params == null) || !params.isZoomSupported() 278 || (mZoomRenderer == null)) return; 279 mZoomMax = params.getMaxZoom(); 280 mZoomRatios = params.getZoomRatios(); 281 // Currently we use immediate zoom for fast zooming to get better UX and 282 // there is no plan to take advantage of the smooth zoom. 283 if (mZoomRenderer != null) { 284 mZoomRenderer.setZoomMax(mZoomMax); 285 mZoomRenderer.setZoom(params.getZoom()); 286 mZoomRenderer.setZoomValue(mZoomRatios.get(params.getZoom())); 287 mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener()); 288 } 289 } 290 291 public void enableGestures(boolean enable) { 292 if (mGestures != null) { 293 mGestures.setEnabled(enable); 294 } 295 } 296 297 public void showGpsOnScreenIndicator(boolean hasSignal) { } 298 299 public void hideGpsOnScreenIndicator() { } 300 301 public void overrideSettings(final String ... keyvalues) { 302 mMenu.overrideSettings(keyvalues); 303 } 304 305 public void updateOnScreenIndicators(Camera.Parameters params, 306 ComboPreferences prefs) { 307 if (params == null) return; 308 updateSceneOnScreenIndicator(params.getSceneMode()); 309 updateExposureOnScreenIndicator(params, 310 CameraSettings.readExposure(prefs)); 311 updateFlashOnScreenIndicator(params.getFlashMode()); 312 updateHdrOnScreenIndicator(params.getSceneMode()); 313 } 314 315 private void updateExposureOnScreenIndicator(Camera.Parameters params, int value) { 316 if (mExposureIndicator == null) { 317 return; 318 } 319 int id = 0; 320 float step = params.getExposureCompensationStep(); 321 value = (int) Math.round(value * step); 322 switch(value) { 323 case -3: 324 id = R.drawable.ic_indicator_ev_n3; 325 break; 326 case -2: 327 id = R.drawable.ic_indicator_ev_n2; 328 break; 329 case -1: 330 id = R.drawable.ic_indicator_ev_n1; 331 break; 332 case 0: 333 id = R.drawable.ic_indicator_ev_0; 334 break; 335 case 1: 336 id = R.drawable.ic_indicator_ev_p1; 337 break; 338 case 2: 339 id = R.drawable.ic_indicator_ev_p2; 340 break; 341 case 3: 342 id = R.drawable.ic_indicator_ev_p3; 343 break; 344 } 345 mExposureIndicator.setImageResource(id); 346 } 347 348 private void updateFlashOnScreenIndicator(String value) { 349 if (mFlashIndicator == null) { 350 return; 351 } 352 if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) { 353 mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); 354 } else { 355 if (Parameters.FLASH_MODE_AUTO.equals(value)) { 356 mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_auto); 357 } else if (Parameters.FLASH_MODE_ON.equals(value)) { 358 mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_on); 359 } else { 360 mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); 361 } 362 } 363 } 364 365 private void updateSceneOnScreenIndicator(String value) { 366 if (mSceneIndicator == null) { 367 return; 368 } 369 if ((value == null) || Parameters.SCENE_MODE_AUTO.equals(value) 370 || Parameters.SCENE_MODE_HDR.equals(value)) { 371 mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_off); 372 } else { 373 mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_on); 374 } 375 } 376 377 private void updateHdrOnScreenIndicator(String value) { 378 if (mHdrIndicator == null) { 379 return; 380 } 381 if ((value != null) && Parameters.SCENE_MODE_HDR.equals(value)) { 382 mHdrIndicator.setImageResource(R.drawable.ic_indicator_hdr_on); 383 } else { 384 mHdrIndicator.setImageResource(R.drawable.ic_indicator_hdr_off); 385 } 386 } 387 388 public void setCameraState(int state) { 389 } 390 391 public boolean dispatchTouchEvent(MotionEvent m) { 392 if (mGestures != null && mRenderOverlay != null) { 393 return mGestures.dispatchTouch(m); 394 } 395 return false; 396 } 397 398 public boolean onBackPressed() { 399 if (mPieRenderer != null && mPieRenderer.showsItems()) { 400 mPieRenderer.hide(); 401 return true; 402 } 403 // In image capture mode, back button should: 404 // 1) if there is any popup, dismiss them, 2) otherwise, get out of 405 // image capture 406 if (mController.isImageCaptureIntent()) { 407 if (!removeTopLevelPopup()) { 408 // no popup to dismiss, cancel image capture 409 mController.onCaptureCancelled(); 410 } 411 return true; 412 } else if (!mController.isCameraIdle()) { 413 // ignore backs while we're taking a picture 414 return true; 415 } else { 416 return removeTopLevelPopup(); 417 } 418 } 419 420 public void onFullScreenChanged(boolean full) { 421 if (mFaceView != null) { 422 mFaceView.setBlockDraw(!full); 423 } 424 if (mPopup != null) { 425 dismissPopup(false, full); 426 } 427 if (mGestures != null) { 428 mGestures.setEnabled(full); 429 } 430 if (mRenderOverlay != null) { 431 // this can not happen in capture mode 432 mRenderOverlay.setVisibility(full ? View.VISIBLE : View.GONE); 433 } 434 if (mPieRenderer != null) { 435 mPieRenderer.setBlockFocus(!full); 436 } 437 setShowMenu(full); 438 if (mBlocker != null) { 439 mBlocker.setVisibility(full ? View.VISIBLE : View.GONE); 440 } 441 if (!full && mCountDownView != null) mCountDownView.cancelCountDown(); 442 } 443 444 public boolean removeTopLevelPopup() { 445 // Remove the top level popup or dialog box and return true if there's any 446 if (mPopup != null) { 447 dismissPopup(true); 448 return true; 449 } 450 return false; 451 } 452 453 public void showPopup(AbstractSettingPopup popup) { 454 mActivity.hideUI(); 455 mBlocker.setVisibility(View.INVISIBLE); 456 setShowMenu(false); 457 mPopup = popup; 458 mPopup.setVisibility(View.VISIBLE); 459 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, 460 LayoutParams.WRAP_CONTENT); 461 lp.gravity = Gravity.CENTER; 462 ((FrameLayout) mRootView).addView(mPopup, lp); 463 mGestures.addTouchReceiver(mPopup); 464 } 465 466 public void dismissPopup(boolean topPopupOnly) { 467 dismissPopup(topPopupOnly, true); 468 } 469 470 private void dismissPopup(boolean topOnly, boolean fullScreen) { 471 if (fullScreen) { 472 mActivity.showUI(); 473 mBlocker.setVisibility(View.VISIBLE); 474 } 475 setShowMenu(fullScreen); 476 if (mPopup != null) { 477 mGestures.removeTouchReceiver(mPopup); 478 ((FrameLayout) mRootView).removeView(mPopup); 479 mPopup = null; 480 } 481 mMenu.popupDismissed(topOnly); 482 } 483 484 public void onShowSwitcherPopup() { 485 if (mPieRenderer != null && mPieRenderer.showsItems()) { 486 mPieRenderer.hide(); 487 } 488 } 489 490 private void setShowMenu(boolean show) { 491 if (mOnScreenIndicators != null) { 492 mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE); 493 } 494 if (mMenuButton != null) { 495 mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE); 496 } 497 } 498 499 public boolean collapseCameraControls() { 500 // Remove all the popups/dialog boxes 501 boolean ret = false; 502 if (mPopup != null) { 503 dismissPopup(false); 504 ret = true; 505 } 506 return ret; 507 } 508 509 protected void showPostCaptureAlert() { 510 mOnScreenIndicators.setVisibility(View.GONE); 511 mMenuButton.setVisibility(View.GONE); 512 Util.fadeIn(mReviewDoneButton); 513 mShutterButton.setVisibility(View.INVISIBLE); 514 Util.fadeIn(mReviewRetakeButton); 515 } 516 517 protected void hidePostCaptureAlert() { 518 mOnScreenIndicators.setVisibility(View.VISIBLE); 519 mMenuButton.setVisibility(View.VISIBLE); 520 Util.fadeOut(mReviewDoneButton); 521 mShutterButton.setVisibility(View.VISIBLE); 522 Util.fadeOut(mReviewRetakeButton); 523 } 524 525 public void setDisplayOrientation(int orientation) { 526 if (mFaceView != null) { 527 mFaceView.setDisplayOrientation(orientation); 528 } 529 } 530 531 // shutter button handling 532 533 public boolean isShutterPressed() { 534 return mShutterButton.isPressed(); 535 } 536 537 // focus handling 538 539 540 private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener { 541 @Override 542 public void onZoomValueChanged(int index) { 543 int newZoom = mController.onZoomChanged(index); 544 if (mZoomRenderer != null) { 545 mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom)); 546 } 547 } 548 549 @Override 550 public void onZoomStart() { 551 if (mPieRenderer != null) { 552 mPieRenderer.setBlockFocus(true); 553 } 554 } 555 556 @Override 557 public void onZoomEnd() { 558 if (mPieRenderer != null) { 559 mPieRenderer.setBlockFocus(false); 560 } 561 } 562 } 563 564 @Override 565 public void onPieOpened(int centerX, int centerY) { 566 mActivity.cancelActivityTouchHandling(); 567 mActivity.setSwipingEnabled(false); 568 if (mFaceView != null) { 569 mFaceView.setBlockDraw(true); 570 } 571 } 572 573 @Override 574 public void onPieClosed() { 575 mActivity.setSwipingEnabled(true); 576 if (mFaceView != null) { 577 mFaceView.setBlockDraw(false); 578 } 579 } 580 581 // Surface Listener 582 583 @Override 584 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 585 Log.v(TAG, "surfaceChanged:" + holder + " width=" + width + ". height=" 586 + height); 587 } 588 589 @Override 590 public void surfaceCreated(SurfaceHolder holder) { 591 Log.v(TAG, "surfaceCreated: " + holder); 592 mSurfaceHolder = holder; 593 mController.onSurfaceCreated(holder); 594 } 595 596 @Override 597 public void surfaceDestroyed(SurfaceHolder holder) { 598 Log.v(TAG, "surfaceDestroyed: " + holder); 599 mSurfaceHolder = null; 600 mController.stopPreview(); 601 } 602 603 public Object getSurfaceTexture() { 604 return mSurfaceTexture; 605 } 606 607 public void setSurfaceTexture(Object st) { 608 mSurfaceTexture = st; 609 } 610 611 public SurfaceHolder getSurfaceHolder() { 612 return mSurfaceHolder; 613 } 614 615 public boolean isCountingDown() { 616 return mCountDownView.isCountingDown(); 617 } 618 619 public void cancelCountDown() { 620 mCountDownView.cancelCountDown(); 621 } 622 623 public void startCountDown(int sec, boolean playSound) { 624 mCountDownView.startCountDown(sec, playSound); 625 } 626 627 public void showPreferencesToast() { 628 if (mNotSelectableToast == null) { 629 String str = mActivity.getResources().getString(R.string.not_selectable_in_scene_mode); 630 mNotSelectableToast = Toast.makeText(mActivity, str, Toast.LENGTH_SHORT); 631 } 632 mNotSelectableToast.show(); 633 } 634 635 public void onPause() { 636 mCountDownView.cancelCountDown(); 637 // Close the camera now because other activities may need to use it. 638 mSurfaceTexture = null; 639 640 // Clear UI. 641 collapseCameraControls(); 642 if (mFaceView != null) mFaceView.clear(); 643 644 645 mRootView.removeOnLayoutChangeListener(mLayoutListener); 646 mPreviewWidth = 0; 647 mPreviewHeight = 0; 648 } 649 650 public void enableShutter(boolean enabled) { 651 if (mShutterButton != null) { 652 mShutterButton.setEnabled(enabled); 653 } 654 } 655 656 public void pressShutterButton() { 657 if (mShutterButton.isInTouchMode()) { 658 mShutterButton.requestFocusFromTouch(); 659 } else { 660 mShutterButton.requestFocus(); 661 } 662 mShutterButton.setPressed(true); 663 } 664 665 // forward from preview gestures to controller 666 @Override 667 public void onSingleTapUp(View view, int x, int y) { 668 mController.onSingleTapUp(view, x, y); 669 } 670 671 // focus UI implementation 672 673 private FocusIndicator getFocusIndicator() { 674 return (mFaceView != null && mFaceView.faceExists()) ? mFaceView : mPieRenderer; 675 } 676 677 @Override 678 public boolean hasFaces() { 679 return (mFaceView != null && mFaceView.faceExists()); 680 } 681 682 public void clearFaces() { 683 if (mFaceView != null) mFaceView.clear(); 684 } 685 686 @Override 687 public void clearFocus() { 688 FocusIndicator indicator = getFocusIndicator(); 689 if (indicator != null) indicator.clear(); 690 } 691 692 @Override 693 public void setFocusPosition(int x, int y) { 694 mPieRenderer.setFocus(x, y); 695 } 696 697 @Override 698 public void onFocusStarted() { 699 getFocusIndicator().showStart(); 700 } 701 702 @Override 703 public void onFocusSucceeded(boolean timeout) { 704 getFocusIndicator().showSuccess(timeout); 705 } 706 707 @Override 708 public void onFocusFailed(boolean timeout) { 709 getFocusIndicator().showFail(timeout); 710 } 711 712 @Override 713 public void pauseFaceDetection() { 714 if (mFaceView != null) mFaceView.pause(); 715 } 716 717 @Override 718 public void resumeFaceDetection() { 719 if (mFaceView != null) mFaceView.resume(); 720 } 721 722 public void onStartFaceDetection(int orientation, boolean mirror) { 723 mFaceView.clear(); 724 mFaceView.setVisibility(View.VISIBLE); 725 mFaceView.setDisplayOrientation(orientation); 726 mFaceView.setMirror(mirror); 727 mFaceView.resume(); 728 } 729 730 @Override 731 public void onFaceDetection(Face[] faces, android.hardware.Camera camera) { 732 mFaceView.setFaces(faces); 733 } 734 735 @Override 736 public void onSwipe(int direction) { 737 if (direction == PreviewGestures.DIR_UP) { 738 openMenu(); 739 } 740 } 741 742} 743