blob: 278bb16327e7f1bdf8cb2c2e27452b757c3fd385 [file] [log] [blame]
Erin Dahlgren165bb8d2014-01-30 14:11:20 -08001/*
2 * Copyright (C) 2014 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.widget;
18
19import android.content.Context;
20import android.content.res.Configuration;
Erin Dahlgren9ec6c492014-02-14 14:14:18 -080021import android.graphics.Matrix;
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080022import android.graphics.RectF;
23import android.util.AttributeSet;
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080024import android.view.Gravity;
25import android.view.MotionEvent;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.FrameLayout;
Erin Dahlgren6e07fe22014-02-03 15:55:31 -080029import android.widget.ImageView;
30import android.widget.LinearLayout;
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080031
Erin Dahlgren5d187692014-02-25 19:16:12 -080032import com.android.camera.ShutterButton;
Angus Kong2bca2102014-03-11 16:27:30 -070033import com.android.camera.debug.Log;
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080034import com.android.camera.ui.PreviewOverlay;
35import com.android.camera.ui.PreviewStatusListener;
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080036import com.android.camera2.R;
37
38/**
39 * ModeOptionsOverlay is a FrameLayout which positions mode options in
40 * in the bottom of the preview that is visible above the bottom bar.
41 */
42public class ModeOptionsOverlay extends FrameLayout
Angus Kong2bacca72014-03-06 12:57:29 -080043 implements PreviewStatusListener.PreviewAreaChangedListener,
Erin Dahlgren6e07fe22014-02-03 15:55:31 -080044 PreviewOverlay.OnPreviewTouchedListener,
Erin Dahlgren5d187692014-02-25 19:16:12 -080045 IndicatorIconController.OnIndicatorVisibilityChangedListener,
46 ShutterButton.OnShutterButtonListener {
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080047
Angus Kong2bca2102014-03-11 16:27:30 -070048 private final static Log.Tag TAG = new Log.Tag("ModeOptionsOverlay");
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080049
50 private static final int BOTTOMBAR_OPTIONS_TIMEOUT_MS = 2000;
51 private final static int BOTTOM_RIGHT = Gravity.BOTTOM | Gravity.RIGHT;
52 private final static int TOP_RIGHT = Gravity.TOP | Gravity.RIGHT;
53
54 private int mPreviewWidth;
55 private int mPreviewHeight;
56
Spike Sprague82fa6ae2014-02-27 14:33:21 -080057 private ModeOptions mModeOptions;
Erin Dahlgren6e07fe22014-02-03 15:55:31 -080058
59 // The mode options toggle can be either a default image, or a
60 // group of on screen indicators.
61 private FrameLayout mModeOptionsToggle;
62 // Default image for mode options toggle.
63 private ImageView mThreeDots;
64 // Group of on screen indicators for mode options toggle.
65 private LinearLayout mIndicators;
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080066
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080067 public ModeOptionsOverlay(Context context, AttributeSet attrs) {
68 super(context, attrs);
69 }
70
71 @Override
72 public void onFinishInflate() {
Spike Sprague82fa6ae2014-02-27 14:33:21 -080073 mModeOptions = (ModeOptions) findViewById(R.id.mode_options);
Erin Dahlgren37452542014-02-25 16:21:22 -080074 mModeOptions.setClickable(true);
75 mModeOptions.setOnClickListener(new View.OnClickListener() {
Spike Sprague591eec62014-03-06 12:37:11 -080076 @Override
77 public void onClick(View v) {
78 closeModeOptions();
79 }
80 });
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080081
Erin Dahlgren6e07fe22014-02-03 15:55:31 -080082 mModeOptionsToggle = (FrameLayout) findViewById(R.id.mode_options_toggle);
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080083 mModeOptionsToggle.setOnClickListener(new View.OnClickListener() {
Spike Sprague82fa6ae2014-02-27 14:33:21 -080084 @Override
85 public void onClick(View v) {
86 mModeOptions.animateVisible();
87 }
88 });
89 mModeOptions.setViewToShowHide(mModeOptionsToggle);
Erin Dahlgren6e07fe22014-02-03 15:55:31 -080090
91 mThreeDots = (ImageView) findViewById(R.id.three_dots);
92 mIndicators = (LinearLayout) findViewById(R.id.indicator_icons);
93 showCorrectToggleView(mThreeDots, mIndicators);
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080094 }
95
96 @Override
97 public void onPreviewTouched(MotionEvent ev) {
Erin Dahlgren37452542014-02-25 16:21:22 -080098 closeModeOptions();
Erin Dahlgren165bb8d2014-01-30 14:11:20 -080099 }
100
Erin Dahlgren6e07fe22014-02-03 15:55:31 -0800101 @Override
102 public void onIndicatorVisibilityChanged(View indicator) {
103 showCorrectToggleView(mThreeDots, mIndicators);
104 }
105
Erin Dahlgren5d187692014-02-25 19:16:12 -0800106 @Override
107 public void onShutterButtonClick() {
108 closeModeOptions();
109 }
110
111 @Override
112 public void onShutterButtonFocus(boolean pressed) {
113 }
114
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800115 /**
116 * Schedule (or re-schedule) the options menu to be closed after a number
117 * of milliseconds. If the options menu is already closed, nothing is
118 * scheduled.
119 */
Erin Dahlgren37452542014-02-25 16:21:22 -0800120 private void closeModeOptions() {
Spike Sprague82fa6ae2014-02-27 14:33:21 -0800121 mModeOptions.animateHidden();
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800122 }
123
124 @Override
125 public void onConfigurationChanged(Configuration configuration) {
126 super.onConfigurationChanged(configuration);
127 checkOrientation(configuration.orientation);
128 }
129
130 @Override
Angus Kong2bacca72014-03-06 12:57:29 -0800131 public void onPreviewAreaChanged(RectF previewArea) {
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800132 mPreviewWidth = (int) previewArea.width();
133 mPreviewHeight = (int) previewArea.height();
Angus Kongfe609792014-02-07 11:20:00 -0800134 setLayoutDimensions();
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800135 }
136
137 /**
138 * The overlay takes its horizontal dimension from the preview. The vertical
139 * dimension of the overlay is determined by its parent layout, which has
140 * knowledge of the bottom bar dimensions.
141 */
142 private void setLayoutDimensions() {
143 if (mPreviewWidth == 0 || mPreviewHeight == 0) {
144 return;
145 }
146
147 boolean isPortrait = Configuration.ORIENTATION_PORTRAIT
148 == getResources().getConfiguration().orientation;
149
150 ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams();
151 if (isPortrait) {
152 params.width = mPreviewWidth;
153 } else {
154 params.height = mPreviewHeight;
155 }
156 setLayoutParams(params);
157 }
158
159 /**
160 * Set the layout gravity of the child layout to be bottom or top right
161 * depending on orientation.
162 */
163 private void checkOrientation(int orientation) {
164 final boolean isPortrait = Configuration.ORIENTATION_PORTRAIT == orientation;
165
166 FrameLayout.LayoutParams modeOptionsParams
167 = (FrameLayout.LayoutParams) mModeOptions.getLayoutParams();
Erin Dahlgren9ec6c492014-02-14 14:14:18 -0800168 FrameLayout.LayoutParams modeOptionsToggleParams
169 = (FrameLayout.LayoutParams) mModeOptionsToggle.getLayoutParams();
170
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800171 if (isPortrait) {
172 modeOptionsParams.height = modeOptionsParams.width;
173 modeOptionsParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
174 if (modeOptionsParams.gravity != Gravity.BOTTOM) {
175 modeOptionsParams.gravity = Gravity.BOTTOM;
176 }
Erin Dahlgren9ec6c492014-02-14 14:14:18 -0800177
178 if (modeOptionsToggleParams.gravity != BOTTOM_RIGHT) {
179 modeOptionsToggleParams.gravity = BOTTOM_RIGHT;
180 }
181
182 // Remove the rotation on the three dots.
183 mThreeDots.setImageMatrix(new Matrix());
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800184 } else if (!isPortrait) {
185 modeOptionsParams.width = modeOptionsParams.height;
186 modeOptionsParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
187 if (modeOptionsParams.gravity != Gravity.RIGHT) {
188 modeOptionsParams.gravity = Gravity.RIGHT;
189 }
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800190
Erin Dahlgren9ec6c492014-02-14 14:14:18 -0800191 if (modeOptionsToggleParams.gravity != TOP_RIGHT) {
192 modeOptionsToggleParams.gravity = TOP_RIGHT;
193 }
194
195 // Rotate the three dots 90 to match portrait.
196 Matrix matrix = new Matrix();
197 matrix.setRotate(90, mThreeDots.getWidth() / 2 , mThreeDots.getHeight() / 2);
198 mThreeDots.setImageMatrix(matrix);
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800199 }
200
201 requestLayout();
202 }
Erin Dahlgren6e07fe22014-02-03 15:55:31 -0800203
204 /**
205 * Show the correct toggle view: the default view if the group has
206 * no visible children, otherwise the default view.
207 */
208 private void showCorrectToggleView(View defaultView, ViewGroup group) {
209 if (getVisibleChildCount(group) > 0) {
210 defaultView.setVisibility(View.GONE);
211 group.setVisibility(View.VISIBLE);
212 } else {
213 group.setVisibility(View.GONE);
214 defaultView.setVisibility(View.VISIBLE);
215 }
216 }
217
218 /**
219 * Get the number of a ViewGroup's visible children.
220 */
221 private int getVisibleChildCount(ViewGroup group) {
222 int visible = 0;
223 for (int i = 0; i < group.getChildCount(); i++) {
224 View child = group.getChildAt(i);
225 if (child != null && child.getVisibility() == View.VISIBLE) {
226 visible++;
227 }
228 }
229 return visible;
230 }
Erin Dahlgren165bb8d2014-01-30 14:11:20 -0800231}