VideoUI.java revision d8de077f72b04cee1bdf26e5ca1678ac5297bd71
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.graphics.Bitmap; 20import android.graphics.SurfaceTexture; 21import android.hardware.Camera.Parameters; 22import android.util.Log; 23import android.view.GestureDetector; 24import android.view.MotionEvent; 25import android.view.View; 26import android.view.ViewGroup; 27import android.widget.ImageView; 28import android.widget.LinearLayout; 29import android.widget.TextView; 30 31import com.android.camera.ui.FocusOverlay; 32import com.android.camera.ui.PreviewOverlay; 33import com.android.camera.ui.PreviewStatusListener; 34import com.android.camera.ui.RotateLayout; 35import com.android.camera.util.CameraUtil; 36import com.android.camera2.R; 37 38import java.util.List; 39 40public class VideoUI implements PreviewStatusListener { 41 private static final String TAG = "VideoUI"; 42 43 private final static float UNSET = 0f; 44 private final PreviewOverlay mPreviewOverlay; 45 // module fields 46 private final CameraActivity mActivity; 47 private final View mRootView; 48 private final FocusOverlay mFocusUI; 49 // An review image having same size as preview. It is displayed when 50 // recording is stopped in capture intent. 51 private ImageView mReviewImage; 52 private View mReviewCancelButton; 53 private View mReviewDoneButton; 54 private View mReviewPlayButton; 55 private TextView mRecordingTimeView; 56 private LinearLayout mLabelsLinearLayout; 57 private View mTimeLapseLabel; 58 private RotateLayout mRecordingTimeRect; 59 private boolean mRecordingStarted = false; 60 private final VideoController mController; 61 private int mZoomMax; 62 private List<Integer> mZoomRatios; 63 64 private float mAspectRatio = UNSET; 65 private final AnimationManager mAnimationManager; 66 67 @Override 68 public void onPreviewLayoutChanged(View v, int left, int top, int right, 69 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 70 } 71 72 @Override 73 public boolean shouldAutoAdjustTransformMatrixOnLayout() { 74 return true; 75 } 76 77 @Override 78 public boolean shouldAutoAdjustBottomBar() { 79 return true; 80 } 81 82 @Override 83 public void onPreviewFlipped() { 84 mController.updateCameraOrientation(); 85 } 86 87 private final GestureDetector.OnGestureListener mPreviewGestureListener 88 = new GestureDetector.SimpleOnGestureListener() { 89 @Override 90 public boolean onSingleTapUp(MotionEvent ev) { 91 mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY()); 92 return true; 93 } 94 }; 95 96 public VideoUI(CameraActivity activity, VideoController controller, View parent) { 97 mActivity = activity; 98 mController = controller; 99 mRootView = parent; 100 ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout); 101 mActivity.getLayoutInflater().inflate(R.layout.video_module, 102 moduleRoot, true); 103 104 mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay); 105 106 initializeMiscControls(); 107 mAnimationManager = new AnimationManager(); 108 mFocusUI = (FocusOverlay) mRootView.findViewById(R.id.focus_overlay); 109 } 110 111 public void setPreviewSize(int width, int height) { 112 if (width == 0 || height == 0) { 113 Log.w(TAG, "Preview size should not be 0."); 114 return; 115 } 116 float aspectRatio; 117 if (width > height) { 118 aspectRatio = (float) width / height; 119 } else { 120 aspectRatio = (float) height / width; 121 } 122 setAspectRatio(aspectRatio); 123 } 124 125 public FocusOverlayManager.FocusUI getFocusUI() { 126 return mFocusUI; 127 } 128 129 /** 130 * Starts a flash animation 131 */ 132 public void animateFlash() { 133 mController.startPreCaptureAnimation(); 134 } 135 136 /** 137 * Cancels on-going animations 138 */ 139 public void cancelAnimations() { 140 mAnimationManager.cancelAnimations(); 141 } 142 143 public void setOrientationIndicator(int orientation, boolean animation) { 144 // We change the orientation of the linearlayout only for phone UI 145 // because when in portrait the width is not enough. 146 if (mLabelsLinearLayout != null) { 147 if (((orientation / 90) & 1) == 0) { 148 mLabelsLinearLayout.setOrientation(LinearLayout.VERTICAL); 149 } else { 150 mLabelsLinearLayout.setOrientation(LinearLayout.HORIZONTAL); 151 } 152 } 153 mRecordingTimeRect.setOrientation(0, animation); 154 } 155 156 private void initializeMiscControls() { 157 mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image); 158 mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time); 159 mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect); 160 mTimeLapseLabel = mRootView.findViewById(R.id.time_lapse_label); 161 // The R.id.labels can only be found in phone layout. 162 // That is, mLabelsLinearLayout should be null in tablet layout. 163 mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels); 164 } 165 166 public void updateOnScreenIndicators(Parameters param) { 167 } 168 169 public void setAspectRatio(float ratio) { 170 if (ratio <= 0) { 171 return; 172 } 173 float aspectRatio = ratio > 1 ? ratio : 1 / ratio; 174 if (aspectRatio != mAspectRatio) { 175 mAspectRatio = aspectRatio; 176 mController.updatePreviewAspectRatio(mAspectRatio); 177 } 178 } 179 180 public void showTimeLapseUI(boolean enable) { 181 if (mTimeLapseLabel != null) { 182 mTimeLapseLabel.setVisibility(enable ? View.VISIBLE : View.GONE); 183 } 184 } 185 186 public void enableShutter(boolean enable) { 187 188 } 189 190 public void setSwipingEnabled(boolean enable) { 191 mActivity.setSwipingEnabled(enable); 192 } 193 194 public void showPreviewBorder(boolean enable) { 195 // TODO: mPreviewFrameLayout.showBorder(enable); 196 } 197 198 public void showRecordingUI(boolean recording) { 199 mRecordingStarted = recording; 200 if (recording) { 201 mRecordingTimeView.setText(""); 202 mRecordingTimeView.setVisibility(View.VISIBLE); 203 } else { 204 mRecordingTimeView.setVisibility(View.GONE); 205 } 206 } 207 208 public void showReviewImage(Bitmap bitmap) { 209 mReviewImage.setImageBitmap(bitmap); 210 mReviewImage.setVisibility(View.VISIBLE); 211 } 212 213 public void showReviewControls() { 214 mActivity.getCameraAppUI().transitionToIntentReviewLayout(); 215 mReviewImage.setVisibility(View.VISIBLE); 216 } 217 218 public void hideReviewUI() { 219 mReviewImage.setVisibility(View.GONE); 220 CameraUtil.fadeOut(mReviewDoneButton); 221 CameraUtil.fadeOut(mReviewPlayButton); 222 } 223 224 public void initializeZoom(Parameters param) { 225 mZoomMax = param.getMaxZoom(); 226 mZoomRatios = param.getZoomRatios(); 227 // Currently we use immediate zoom for fast zooming to get better UX and 228 // there is no plan to take advantage of the smooth zoom. 229 // TODO: setup zoom through App UI. 230 mPreviewOverlay.setupZoom(mZoomMax, param.getZoom(), mZoomRatios, new ZoomChangeListener()); 231 } 232 233 public void clickShutter() { 234 235 } 236 237 public void pressShutter(boolean pressed) { 238 239 } 240 241 public View getShutterButton() { 242 return null; 243 } 244 245 public void setRecordingTime(String text) { 246 mRecordingTimeView.setText(text); 247 } 248 249 public void setRecordingTimeTextColor(int color) { 250 mRecordingTimeView.setTextColor(color); 251 } 252 253 public boolean isVisible() { 254 return false; 255 } 256 257 @Override 258 public GestureDetector.OnGestureListener getGestureListener() { 259 return mPreviewGestureListener; 260 } 261 262 @Override 263 public View.OnTouchListener getTouchListener() { 264 return null; 265 } 266 267 /** 268 * Shows or hides focus UI. 269 * 270 * @param show shows focus UI when true, hides it otherwise 271 */ 272 public void showFocusUI(boolean show) { 273 if (mFocusUI != null) { 274 mFocusUI.setVisibility(show ? View.VISIBLE : View.INVISIBLE); 275 } 276 } 277 278 private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener { 279 @Override 280 public void onZoomValueChanged(int index) { 281 mController.onZoomChanged(index); 282 } 283 284 @Override 285 public void onZoomStart() { 286 } 287 288 @Override 289 public void onZoomEnd() { 290 } 291 } 292 293 // SurfaceTexture callbacks 294 @Override 295 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 296 mController.onPreviewUIReady(); 297 } 298 299 @Override 300 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 301 mController.onPreviewUIDestroyed(); 302 Log.d(TAG, "surfaceTexture is destroyed"); 303 return true; 304 } 305 306 @Override 307 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 308 } 309 310 @Override 311 public void onSurfaceTextureUpdated(SurfaceTexture surface) { 312 } 313} 314