1 /* 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 17 package com.android.camera.widget; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.graphics.RectF; 22 import android.util.AttributeSet; 23 import android.view.Gravity; 24 import android.view.MotionEvent; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.widget.FrameLayout; 28 import android.widget.ImageView; 29 import android.widget.LinearLayout; 30 31 import com.android.camera.CaptureLayoutHelper; 32 import com.android.camera.ShutterButton; 33 import com.android.camera.debug.Log; 34 import com.android.camera.ui.PreviewOverlay; 35 import com.android.camera.ui.TouchCoordinate; 36 import 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 */ 42 public class ModeOptionsOverlay extends FrameLayout 43 implements PreviewOverlay.OnPreviewTouchedListener, 44 ShutterButton.OnShutterButtonListener { 45 46 private final static Log.Tag TAG = new Log.Tag("ModeOptionsOverlay"); 47 48 private static final int BOTTOMBAR_OPTIONS_TIMEOUT_MS = 2000; 49 private static final int BOTTOM_RIGHT = Gravity.BOTTOM | Gravity.RIGHT; 50 private static final int TOP_RIGHT = Gravity.TOP | Gravity.RIGHT; 51 52 private ModeOptions mModeOptions; 53 // need a reference to set the onClickListener and fix the layout gravity on orientation change 54 private LinearLayout mModeOptionsToggle; 55 // need a reference to fix the rotation on orientation change 56 private ImageView mThreeDots; 57 private CaptureLayoutHelper mCaptureLayoutHelper = null; 58 ModeOptionsOverlay(Context context, AttributeSet attrs)59 public ModeOptionsOverlay(Context context, AttributeSet attrs) { 60 super(context, attrs); 61 } 62 63 /** 64 * Whether the mode options are hidden. 65 */ isModeOptionsHidden()66 public boolean isModeOptionsHidden() { 67 return mModeOptions.isHiddenOrHiding(); 68 } 69 70 /** 71 * Gets the current width of the mode options toggle including the three dots and various mode 72 * option indicators. 73 */ getModeOptionsToggleWidth()74 public float getModeOptionsToggleWidth() { 75 return mModeOptionsToggle.getWidth(); 76 } 77 78 /** 79 * Sets a capture layout helper to query layout rect from. 80 */ setCaptureLayoutHelper(CaptureLayoutHelper helper)81 public void setCaptureLayoutHelper(CaptureLayoutHelper helper) { 82 mCaptureLayoutHelper = helper; 83 } 84 setToggleClickable(boolean clickable)85 public void setToggleClickable(boolean clickable) { 86 mModeOptionsToggle.setClickable(clickable); 87 } 88 showExposureOptions()89 public void showExposureOptions() { 90 mModeOptions.showExposureOptions(); 91 } 92 93 /** 94 * Sets the mode options listener. 95 * 96 * @param listener The listener to be set. 97 */ setModeOptionsListener(ModeOptions.Listener listener)98 public void setModeOptionsListener(ModeOptions.Listener listener) { 99 mModeOptions.setListener(listener); 100 } 101 102 @Override onFinishInflate()103 public void onFinishInflate() { 104 mModeOptions = (ModeOptions) findViewById(R.id.mode_options); 105 mModeOptions.setClickable(true); 106 mModeOptions.setOnClickListener(new View.OnClickListener() { 107 @Override 108 public void onClick(View v) { 109 closeModeOptions(); 110 } 111 }); 112 113 mModeOptionsToggle = (LinearLayout) findViewById(R.id.mode_options_toggle); 114 mModeOptionsToggle.setOnClickListener(new View.OnClickListener() { 115 @Override 116 public void onClick(View v) { 117 mModeOptions.animateVisible(); 118 } 119 }); 120 mModeOptions.setViewToShowHide(mModeOptionsToggle); 121 122 mThreeDots = (ImageView) findViewById(R.id.three_dots); 123 } 124 125 @Override onPreviewTouched(MotionEvent ev)126 public void onPreviewTouched(MotionEvent ev) { 127 closeModeOptions(); 128 } 129 130 @Override onShutterButtonClick()131 public void onShutterButtonClick() { 132 closeModeOptions(); 133 } 134 135 @Override onShutterCoordinate(TouchCoordinate coord)136 public void onShutterCoordinate(TouchCoordinate coord) { 137 // Do nothing. 138 } 139 140 @Override onShutterButtonFocus(boolean pressed)141 public void onShutterButtonFocus(boolean pressed) { 142 // noop 143 } 144 145 @Override onShutterButtonLongPressed()146 public void onShutterButtonLongPressed() { 147 // noop 148 } 149 150 /** 151 * Schedule (or re-schedule) the options menu to be closed after a number 152 * of milliseconds. If the options menu is already closed, nothing is 153 * scheduled. 154 */ closeModeOptions()155 public void closeModeOptions() { 156 mModeOptions.animateHidden(); 157 } 158 159 @Override onConfigurationChanged(Configuration configuration)160 public void onConfigurationChanged(Configuration configuration) { 161 super.onConfigurationChanged(configuration); 162 checkOrientation(configuration.orientation); 163 } 164 165 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)166 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 167 if (mCaptureLayoutHelper == null) { 168 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 169 Log.e(TAG, "Capture layout helper needs to be set first."); 170 } else { 171 RectF uncoveredPreviewRect = mCaptureLayoutHelper.getUncoveredPreviewRect(); 172 super.onMeasure(MeasureSpec.makeMeasureSpec( 173 (int) uncoveredPreviewRect.width(), MeasureSpec.EXACTLY), 174 MeasureSpec.makeMeasureSpec((int) uncoveredPreviewRect.height(), 175 MeasureSpec.EXACTLY) 176 ); 177 } 178 } 179 180 /** 181 * Set the layout gravity of the child layout to be bottom or top right 182 * depending on orientation. 183 */ checkOrientation(int orientation)184 private void checkOrientation(int orientation) { 185 final boolean isPortrait = (Configuration.ORIENTATION_PORTRAIT == orientation); 186 187 final int modeOptionsDimension = (int) getResources() 188 .getDimension(R.dimen.mode_options_height); 189 190 FrameLayout.LayoutParams modeOptionsParams 191 = (FrameLayout.LayoutParams) mModeOptions.getLayoutParams(); 192 FrameLayout.LayoutParams modeOptionsToggleParams 193 = (FrameLayout.LayoutParams) mModeOptionsToggle.getLayoutParams(); 194 195 if (isPortrait) { 196 modeOptionsParams.height = modeOptionsDimension; 197 modeOptionsParams.width = ViewGroup.LayoutParams.MATCH_PARENT; 198 modeOptionsParams.gravity = Gravity.BOTTOM; 199 200 modeOptionsToggleParams.gravity = BOTTOM_RIGHT; 201 202 mThreeDots.setImageResource(R.drawable.ic_options_port); 203 } else { 204 modeOptionsParams.width = modeOptionsDimension; 205 modeOptionsParams.height = ViewGroup.LayoutParams.MATCH_PARENT; 206 modeOptionsParams.gravity = Gravity.RIGHT; 207 208 modeOptionsToggleParams.gravity = TOP_RIGHT; 209 210 mThreeDots.setImageResource(R.drawable.ic_options_land); 211 } 212 213 requestLayout(); 214 } 215 } 216