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