2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.camera.ui;
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.res.Configuration;
22 import android.graphics.Rect;
23 import android.util.AttributeSet;
24 import android.view.Gravity;
25 import android.view.View;
26 import android.widget.FrameLayout;
28 import com.android.camera.Util;
29 import com.android.gallery3d.R;
31 public class CameraControls extends RotatableLayout {
33 private static final String TAG = "CAM_Controls";
35 private View mBackgroundView;
36 private View mShutter;
37 private View mSwitcher;
39 private View mIndicators;
40 private View mPreview;
42 public CameraControls(Context context, AttributeSet attrs) {
43 super(context, attrs);
46 public CameraControls(Context context) {
51 public void onConfigurationChanged(Configuration config) {
52 super.onConfigurationChanged(config);
57 public void onFinishInflate() {
58 super.onFinishInflate();
59 mBackgroundView = findViewById(R.id.blocker);
60 mSwitcher = findViewById(R.id.camera_switcher);
61 mShutter = findViewById(R.id.shutter_button);
62 mMenu = findViewById(R.id.menu);
63 mIndicators = findViewById(R.id.on_screen_indicators);
64 mPreview = findViewById(R.id.preview_thumb);
68 public void onLayout(boolean changed, int l, int t, int r, int b) {
69 int orientation = getResources().getConfiguration().orientation;
70 int rotation = Util.getDisplayRotation((Activity) getContext());
71 rotation = correctRotation(rotation, orientation);
72 super.onLayout(changed, l, t, r, b);
73 Rect shutter = new Rect();
74 center(mShutter, l, t, r, b, orientation, rotation, shutter);
75 center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect());
76 toLeft(mSwitcher, l, t, r, b, orientation, rotation, shutter);
77 toRight(mMenu, l, t, r, b, orientation, rotation, shutter);
78 toRight(mIndicators, l, t, r, b, orientation, rotation, shutter);
79 topRight(mPreview, l, t, r, b, orientation, rotation);
80 View retake = findViewById(R.id.btn_retake);
82 Rect retakeRect = new Rect();
83 center(retake, l, t, r, b, orientation, rotation, retakeRect);
84 View cancel = findViewById(R.id.btn_cancel);
85 toLeft(cancel, l, t, r, b, orientation, rotation, shutter);
86 View done = findViewById(R.id.btn_done);
87 toRight(done, l, t, r, b, orientation, rotation, shutter);
91 private int correctRotation(int rotation, int orientation) {
92 // all the layout code assumes camera device orientation to be portrait
93 // adjust rotation for landscape
94 int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT
95 : Configuration.ORIENTATION_LANDSCAPE;
96 if (camOrientation != orientation) {
97 return (rotation + 90) % 360;
102 private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) {
103 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
104 int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
105 int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
108 // phone portrait; controls bottom
109 result.left = (r - l) / 2 - tw / 2 + lp.leftMargin;
110 result.right = (r - l) / 2 + tw / 2 - lp.rightMargin;
111 result.bottom = b - lp.bottomMargin;
112 result.top = b - th + lp.topMargin;
115 // phone landscape: controls right
116 result.right = r - lp.rightMargin;
117 result.left = r - tw + lp.leftMargin;
118 result.top = (b - t) / 2 - th / 2 + lp.topMargin;
119 result.bottom = (b - t) / 2 + th / 2 - lp.bottomMargin;
122 // phone upside down: controls top
123 result.left = (r - l) / 2 - tw / 2 + lp.leftMargin;
124 result.right = (r - l) / 2 + tw / 2 - lp.rightMargin;
125 result.top = t + lp.topMargin;
126 result.bottom = t + th - lp.bottomMargin;
129 // reverse landscape: controls left
130 result.left = l + lp.leftMargin;
131 result.right = l + tw - lp.rightMargin;
132 result.top = (b - t) / 2 - th / 2 + lp.topMargin;
133 result.bottom = (b - t) / 2 + th / 2 - lp.bottomMargin;
136 v.layout(result.left, result.top, result.right, result.bottom);
139 private void toLeft(View v, int l, int t, int r, int b, int orientation, int rotation, Rect anchor) {
140 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
141 int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
142 int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
143 Rect result = new Rect();
146 // portrait, to left of anchor at bottom
147 result.right = anchor.left - lp.rightMargin;
148 result.left = anchor.left - tw + lp.leftMargin;
149 result.bottom = b - lp.bottomMargin;
150 result.top = b - th + lp.topMargin;
153 // phone landscape: below anchor on right
154 result.right = r - lp.rightMargin;
155 result.left = r - tw + lp.leftMargin;
156 result.top = anchor.bottom + lp.topMargin;
157 result.bottom = anchor.bottom + th - lp.bottomMargin;
160 // phone upside down: right of anchor at top
161 result.left = anchor.right + lp.leftMargin;
162 result.right = anchor.right + tw - lp.rightMargin;
163 result.top = t + lp.topMargin;
164 result.bottom = t + th - lp.bottomMargin;
167 // reverse landscape: above anchor on left
168 result.left = l + lp.leftMargin;
169 result.right = l + tw - lp.rightMargin;
170 result.bottom = anchor.top - lp.bottomMargin;
171 result.top = anchor.top - th + lp.topMargin;
174 v.layout(result.left, result.top, result.right, result.bottom);
177 private void toRight(View v, int l, int t, int r, int b, int orientation, int rotation, Rect anchor) {
178 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
179 int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
180 int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
181 Rect result = new Rect();
184 // portrait, right of anchor at bottom
185 result.left = anchor.right + lp.leftMargin;
186 result.right = anchor.right + tw - lp.rightMargin;
187 result.bottom = b - lp.bottomMargin;
188 result.top = b - th + lp.topMargin;
191 // phone landscape: above anchor on right
192 result.right = r - lp.rightMargin;
193 result.left = r - tw + lp.leftMargin;
194 result.bottom = anchor.top - lp.bottomMargin;
195 result.top = anchor.top - th + lp.topMargin;
198 // phone upside down: left of anchor at top
199 result.right = anchor.left - lp.rightMargin;
200 result.left = anchor.left - tw + lp.leftMargin;
201 result.top = t + lp.topMargin;
202 result.bottom = t + th - lp.bottomMargin;
205 // reverse landscape: below anchor on left
206 result.left = l + lp.leftMargin;
207 result.right = l + tw - lp.rightMargin;
208 result.top = anchor.bottom + lp.topMargin;
209 result.bottom = anchor.bottom + th - lp.bottomMargin;
212 v.layout(result.left, result.top, result.right, result.bottom);
215 private void topRight(View v, int l, int t, int r, int b, int orientation, int rotation) {
216 // layout using the specific margins; the rotation code messes up the others
217 int mt = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_top);
218 int mr = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_right);
219 v.layout(r - v.getMeasuredWidth() - mr, t + mt, r - mr, t + mt + v.getMeasuredHeight());
222 // In reverse landscape and reverse portrait, camera controls will be laid out
223 // on the wrong side of the screen. We need to make adjustment to move the controls
225 public void adjustControlsToRightPosition() {
226 Configuration config = getResources().getConfiguration();
227 int orientation = Util.getDisplayRotation((Activity) getContext());
228 if (orientation == 270 && config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
231 if (orientation == 180 && config.orientation == Configuration.ORIENTATION_PORTRAIT) {
237 private void adjustBackground() {
238 // remove current drawable and reset rotation
239 mBackgroundView.setBackgroundDrawable(null);
240 mBackgroundView.setRotationX(0);
241 mBackgroundView.setRotationY(0);
242 // if the switcher background is top aligned we need to flip the background
243 // drawable vertically; if left aligned, flip horizontally
244 int gravity = ((LayoutParams) mBackgroundView.getLayoutParams()).gravity;
245 if ((gravity & Gravity.TOP) == Gravity.TOP) {
246 mBackgroundView.setRotationX(180);
247 } else if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
248 mBackgroundView.setRotationY(180);
250 mBackgroundView.setBackgroundResource(R.drawable.switcher_bg);