IndicatorControlWheel.java revision 248232e937007384328592e0c269b42cf03c6899
16f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li/* 26f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * Copyright (C) 2010 The Android Open Source Project 36f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * 46f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * Licensed under the Apache License, Version 2.0 (the "License"); 56f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * you may not use this file except in compliance with the License. 66f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * You may obtain a copy of the License at 76f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * 86f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * http://www.apache.org/licenses/LICENSE-2.0 96f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * 106f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * Unless required by applicable law or agreed to in writing, software 116f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * distributed under the License is distributed on an "AS IS" BASIS, 126f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * See the License for the specific language governing permissions and 146f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li * limitations under the License. 156f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li */ 166f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 176f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Lipackage com.android.camera.ui; 186f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 196f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport com.android.camera.ComboPreferences; 207341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Liimport com.android.camera.IconListPreference; 216f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport com.android.camera.PreferenceGroup; 226f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport com.android.camera.R; 236f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 246f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport android.content.Context; 25e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyanimport android.content.res.Resources; 2680715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Liimport android.graphics.Canvas; 2780715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Liimport android.graphics.Paint; 2880715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Liimport android.graphics.RectF; 29a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Liimport android.os.Handler; 30a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Liimport android.os.SystemClock; 316f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport android.util.AttributeSet; 326f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport android.util.Log; 33d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyanimport android.widget.ImageView; 3422898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Liimport android.view.animation.Animation; 3522898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Liimport android.view.animation.AnimationUtils; 367341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Liimport android.view.LayoutInflater; 37dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Liimport android.view.MotionEvent; 386f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport android.view.ViewGroup; 396f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport android.view.View; 406f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 416f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Liimport java.lang.Math; 427341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Liimport java.util.ArrayList; 436f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 446f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li/** 4580715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li * A view that contains shutter button and camera setting indicators. The 4680715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li * indicators are spreaded around the shutter button. The first child is always 4780715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li * the shutter button. 486f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li */ 497341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Lipublic class IndicatorWheel extends ViewGroup implements 507341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li BasicSettingPopup.Listener, OtherSettingsPopup.Listener { 51f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li private static final String TAG = "IndicatorWheel"; 52e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan // The width of the edges on both sides of the wheel, which has less alpha. 53e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan private static final float EDGE_STROKE_WIDTH = 6f; 54e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan private static final int HIGHLIGHT_WIDTH = 4; 55e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan private static final int HIGHLIGHT_DEGREE = 30; 56a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li private static final int TIME_LAPSE_ARC_WIDTH = 6; 57e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan 58e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan private final int HIGHLIGHT_COLOR; 59e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan private final int DISABLED_COLOR; 60a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li private final int TIME_LAPSE_ARC_COLOR; 61e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan 62dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li private Listener mListener; 6380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li // The center of the shutter button. 64f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li private int mCenterX, mCenterY; 6580715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li // The width of the wheel stroke. 6641ac285a1c97b1df78246456effb80de51033323Hung-ying Tyan private int mStrokeWidth = 60; 6780715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li private View mShutterButton; 68f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li private double mShutterButtonRadius; 6980715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li private double mWheelRadius; 70f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li private double mSectorInitialRadians[]; 7180715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li private Paint mBackgroundPaint; 7280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li private RectF mBackgroundRect; 734504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // The index of the indicator that is currently selected. 7419d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan private int mSelectedIndex = -1; 754504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // The index of the indicator that has been just de-selected. If users click 764504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // on the same indicator, we want to dismiss the popup window without 774504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // opening it again. 784504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li private int mJustDeselectedIndex = -1; 79dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li 80a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li // Time lapse recording variables. 81a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li private int mTimeLapseInterval; // in ms 82a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li private long mRecordingStartTime = 0; 83a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li private long mNumberOfFrames = 0; 84a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li 857341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private Context mContext; 867341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private PreferenceGroup mPreferenceGroup; 877341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private ArrayList<String> mPreferenceKeys; 887341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private BasicSettingPopup[] mBasicSettingPopups; 897341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private OtherSettingsPopup mOtherSettingsPopup; 907341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 9122898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li private Animation mFadeIn, mFadeOut; 9222898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li // The previous view that has the animation. The animation may have stopped. 9322898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li private View mPrevAnimatingView; 9422898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li 95dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li static public interface Listener { 967341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void onSharedPreferenceChanged(); 977341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void onRestorePreferencesClicked(); 987341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void onOverriddenPreferencesClicked(); 99dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li } 100dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li 101dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li public void setListener(Listener listener) { 102dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li mListener = listener; 103dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li } 104dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li 10580715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li public IndicatorWheel(Context context, AttributeSet attrs) { 10680715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li super(context, attrs); 1077341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mContext = context; 108e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan Resources resources = context.getResources(); 109e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan HIGHLIGHT_COLOR = resources.getColor(R.color.review_control_pressed_color); 110e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan DISABLED_COLOR = resources.getColor(R.color.icon_disabled_color); 111a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li TIME_LAPSE_ARC_COLOR = resources.getColor(R.color.time_lapse_arc); 11280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li setWillNotDraw(false); 11380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li 11480715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mBackgroundPaint = new Paint(); 11580715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mBackgroundPaint.setStyle(Paint.Style.STROKE); 11680715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mBackgroundPaint.setAntiAlias(true); 11780715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li 11880715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mBackgroundRect = new RectF(); 11922898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li 12022898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li mFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.grow_fade_in_from_right); 12122898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li mFadeOut = AnimationUtils.loadAnimation(mContext, R.anim.shrink_fade_out_from_right); 12280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li } 12380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li 1244504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li public boolean onInterceptTouchEvent(MotionEvent ev) { 1254504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // If the event will go to shutter button, dismiss the popup window now. 1264504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // If not, handle it in onTouchEvent. 1274504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (ev.getAction() == MotionEvent.ACTION_DOWN) { 1284504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li float x = ev.getX(); 1294504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li float y = ev.getY(); 1304504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li float shutterButtonX = mShutterButton.getX(); 1314504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li float shutterButtonY = mShutterButton.getY(); 1324504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (x >= shutterButtonX && y >= shutterButtonY 1334504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li && (x < shutterButtonX + mShutterButton.getWidth()) 1344504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li && (y < shutterButtonY + mShutterButton.getHeight())) 1354504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li dismissSettingPopup(); 1364504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li } 1374504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li return false; 1384504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li } 1394504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li 140dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li @Override 141dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li public boolean onTouchEvent(MotionEvent event) { 1421c62e1b83c2fdda82c726bf712324444136fdc5dHung-ying Tyan if (!isEnabled()) return false; 1431c62e1b83c2fdda82c726bf712324444136fdc5dHung-ying Tyan 144f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li int count = getChildCount(); 1457341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (count <= 1) return false; 146f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li 147f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li // Check if any setting is pressed. 148f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li int action = event.getAction(); 1497341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE) { 1507341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return false; 1517341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 152f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li 1537341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li double dx = event.getX() - mCenterX; 1547341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li double dy = mCenterY - event.getY(); 1557341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li double radius = Math.sqrt(dx * dx + dy * dy); 1567341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li // Ignore the event if it's too near to the shutter button or too far 1577341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li // from the shutter button. 1587341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 1597341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (radius >= mShutterButtonRadius && radius <= mWheelRadius + mStrokeWidth) { 160f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li double delta = Math.atan2(dy, dx); 161f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li if (delta < 0) delta += Math.PI * 2; 162f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li // Check which sector is pressed. 163f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li if (delta > mSectorInitialRadians[0]) { 164f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li for (int i = 1; i < count; i++) { 165f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li if (delta < mSectorInitialRadians[i]) { 1664504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // If the touch is moving around the same indicator with 1674504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // popup opened, return now to avoid redundent works. 1684504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (action == MotionEvent.ACTION_MOVE && (mSelectedIndex == i - 1)) { 1694504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li return false; 1704504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li } 1714504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li 1724504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li int selectedIndex = mSelectedIndex; 1734504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li dismissSettingPopup(); 1744504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li 17519d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan // Do nothing if scene mode overrides the setting. 176823d57389b616091827059ca6401f675e416a53bWu-cheng Li View child = getChildAt(i); 177823d57389b616091827059ca6401f675e416a53bWu-cheng Li if (child instanceof IndicatorButton) { 17819d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan if (((IndicatorButton) child).isOverridden()) { 179fba0439b62f19a2a19ff6559c1ae055e910400dbWu-cheng Li // Do not notify in ACTION_MOVE to avoid lots of 180fba0439b62f19a2a19ff6559c1ae055e910400dbWu-cheng Li // toast being displayed. 1817341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (action == MotionEvent.ACTION_DOWN && mListener != null) { 1827341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mListener.onOverriddenPreferencesClicked(); 183fba0439b62f19a2a19ff6559c1ae055e910400dbWu-cheng Li } 18419d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan return true; 185823d57389b616091827059ca6401f675e416a53bWu-cheng Li } 186823d57389b616091827059ca6401f675e416a53bWu-cheng Li } 1874504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (action == MotionEvent.ACTION_DOWN 1884504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li && (selectedIndex == i - 1) && (mJustDeselectedIndex != i - 1)) { 1894504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li // The same indicator is pressed with popup opened. 1904504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li mJustDeselectedIndex = i - 1; 1914504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li } else { 1924504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if ((mJustDeselectedIndex != i - 1) 1934504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li || (selectedIndex == -1 && action == MotionEvent.ACTION_DOWN)) { 1944504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li showSettingPopup(i - 1); 1954504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li mJustDeselectedIndex = -1; 1964504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li } 1974504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li } 198f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li return true; 199f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li } 200f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li } 201dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li } 202dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li } 2034504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li dismissSettingPopup(); 2044504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li mJustDeselectedIndex = -1; 205dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li return false; 206dfee7f813adb8de209472d24553b860d2515ea0aWu-cheng Li } 2076f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 20880715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li @Override 20980715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li protected void onFinishInflate() { 21080715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li super.onFinishInflate(); 21180715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li // The first view is shutter button. 21280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mShutterButton = getChildAt(0); 213248232e937007384328592e0c269b42cf03c6899Wu-cheng Li invalidate(); 2146f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 2156f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 216fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin public void removeIndicators() { 217fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin // Remove everything but the shutter button. 218fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin int count = getChildCount(); 219fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin if (count > 1) { 220fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin removeViews(1, count - 1); 221fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin } 222fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin } 223fec1720cda1be572610c601ef6a6d929fb37be65Andrei Warkentin 2246f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li @Override 2256f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li protected void onMeasure(int widthSpec, int heightSpec) { 2266f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li // Measure all children. 22780715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int childCount = getChildCount(); 2286f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 22980715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li for (int i = 0; i < childCount; i++) { 2306f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li getChildAt(i).measure(freeSpec, freeSpec); 2316f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 2326f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 2336f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li // Measure myself. 23441ac285a1c97b1df78246456effb80de51033323Hung-ying Tyan int desiredWidth = (int)(mShutterButton.getMeasuredWidth() * 3); 23541ac285a1c97b1df78246456effb80de51033323Hung-ying Tyan int desiredHeight = (int)(mShutterButton.getMeasuredHeight() * 4.5) + 2; 2366f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li int widthMode = MeasureSpec.getMode(widthSpec); 2376f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li int heightMode = MeasureSpec.getMode(heightSpec); 2386f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li int measuredWidth, measuredHeight; 2396f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li if (widthMode == MeasureSpec.UNSPECIFIED) { 2406f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li measuredWidth = desiredWidth; 2416f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } else if (widthMode == MeasureSpec.AT_MOST) { 2426f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li measuredWidth = Math.min(desiredWidth, MeasureSpec.getSize(widthSpec)); 2436f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } else { // MeasureSpec.EXACTLY 2446f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li measuredWidth = MeasureSpec.getSize(widthSpec); 2456f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 2466f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li if (heightMode == MeasureSpec.UNSPECIFIED) { 2476f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li measuredHeight = desiredHeight; 2486f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } else if (heightMode == MeasureSpec.AT_MOST) { 2496f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li measuredHeight = Math.min(desiredHeight, MeasureSpec.getSize(heightSpec)); 2506f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } else { // MeasureSpec.EXACTLY 2516f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li measuredHeight = MeasureSpec.getSize(heightSpec); 2526f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 2536f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li setMeasuredDimension(measuredWidth, measuredHeight); 2546f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 2556f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 2566f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li @Override 2576f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li protected void onLayout( 2586f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li boolean changed, int left, int top, int right, int bottom) { 2596f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li int count = getChildCount(); 2606f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li if (count == 0) return; 2616f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 2626f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li // Layout the shutter button. 26380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int shutterButtonWidth = mShutterButton.getMeasuredWidth(); 26441ac285a1c97b1df78246456effb80de51033323Hung-ying Tyan mShutterButtonRadius = shutterButtonWidth / 2.0; 26580715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int shutterButtonHeight = mShutterButton.getMeasuredHeight(); 26674c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan mStrokeWidth = (int) (mShutterButtonRadius * 1.05); 2679bd6c4687e40d86d5de95c3998eae7b079170d42Wu-cheng Li int innerRadius = (int) (mShutterButtonRadius + mStrokeWidth * 0.84); 26847335563ade2c03ee37621b49a16d5c6905e3531Wu-cheng Li // 64 is the requirement by UI design. The distance between the center 26947335563ade2c03ee37621b49a16d5c6905e3531Wu-cheng Li // and the border is 64 pixels. This has to be consistent with the 27047335563ade2c03ee37621b49a16d5c6905e3531Wu-cheng Li // background. 27147335563ade2c03ee37621b49a16d5c6905e3531Wu-cheng Li mCenterX = right - left - 64; 27262776cd28a40b4c6ada4b4aa38683f45572ae266Wu-cheng Li mCenterY = (bottom - top) / 2; 27380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mShutterButton.layout(mCenterX - shutterButtonWidth / 2, 27480715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mCenterY - shutterButtonHeight / 2, 27580715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mCenterX + shutterButtonWidth / 2, 27680715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li mCenterY + shutterButtonHeight / 2); 2776f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 2786f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li // Layout the settings. The icons are spreaded on the left side of the 2796f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li // shutter button. So the angle starts from 90 to 270 degrees. 2806f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li if (count == 1) return; 28174c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan mWheelRadius = innerRadius + mStrokeWidth * 0.5; 28219d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan double intervalDegrees = (count == 2) ? 90.0 : 180.0 / (count - 2); 2836f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li double initialDegrees = 90.0; 2846f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li int index = 0; 285f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li for (int i = 0; i < count; i++) { 2866f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li View view = getChildAt(i); 28780715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li if (view == mShutterButton) continue; 2886f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li double degree = initialDegrees + intervalDegrees * index; 289f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li double radian = Math.toRadians(degree); 29080715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int x = mCenterX + (int)(mWheelRadius * Math.cos(radian)); 29180715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int y = mCenterY - (int)(mWheelRadius * Math.sin(radian)); 29280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int width = view.getMeasuredWidth(); 29380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li int height = view.getMeasuredHeight(); 2946f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li view.layout(x - width / 2, y - height / 2, x + width / 2, 2956f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li y + height / 2); 2966f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li index++; 2976f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 2986f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 299f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li // Store the radian intervals for each icon. 300f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li mSectorInitialRadians = new double[count]; 301f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li mSectorInitialRadians[0] = Math.toRadians( 302f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li initialDegrees - intervalDegrees / 2.0); 303f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li for (int i = 1; i < count; i++) { 304f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li mSectorInitialRadians[i] = mSectorInitialRadians[i - 1] 305f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li + Math.toRadians(intervalDegrees); 306f5bffc476b8293b30bb500bed2ab7914bb4ca411Wu-cheng Li } 3076f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li } 3086f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li 309a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li public void startTimeLapseAnimation(int timeLapseInterval, long startTime) { 310a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mTimeLapseInterval = timeLapseInterval; 311a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mRecordingStartTime = startTime; 312a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mNumberOfFrames = 0; 313a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li invalidate(); 314a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li } 315a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li 316a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li public void stopTimeLapseAnimation() { 317a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mTimeLapseInterval = 0; 318a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li invalidate(); 319a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li } 320a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li 32180715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li @Override 32280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li protected void onDraw(Canvas canvas) { 32319d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan // Draw highlight. 32474c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan float delta = mStrokeWidth * 0.5f; 32574c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan float radius = (float) (mWheelRadius + mStrokeWidth * 0.5 + EDGE_STROKE_WIDTH); 32674c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan mBackgroundRect.set((float)(mCenterX - radius), 32774c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan (float)(mCenterY - radius), 32874c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan (float)(mCenterX + radius), 32974c5164d19fa213c6904639e6e6b0d9e542cbf66Hung-ying Tyan (float)(mCenterY + radius)); 33019d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan if (mSelectedIndex >= 0) { 33119d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan int count = getChildCount(); 33219d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan float initialDegrees = 90.0f; 33319d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan float intervalDegrees = (count <= 2) ? 0.0f : 180.0f / (count - 2); 33419d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan float degree = initialDegrees + intervalDegrees * mSelectedIndex; 33519d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan mBackgroundPaint.setStrokeWidth(HIGHLIGHT_WIDTH); 33619d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND); 33719d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan mBackgroundPaint.setColor(HIGHLIGHT_COLOR); 33819d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan canvas.drawArc(mBackgroundRect, -degree - HIGHLIGHT_DEGREE / 2, 33919d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan HIGHLIGHT_DEGREE, false, mBackgroundPaint); 34019d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan } 34119d029b83d65fb2e124f08aa8b98054974fc3acdHung-ying Tyan 342a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li // Draw arc shaped indicator in time lapse recording. 343a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li if (mTimeLapseInterval != 0) { 344a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li // Setup rectangle and paint. 345a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mBackgroundRect.set((float)(mCenterX - mShutterButtonRadius), 346a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li (float)(mCenterY - mShutterButtonRadius), 347a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li (float)(mCenterX + mShutterButtonRadius), 348a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li (float)(mCenterY + mShutterButtonRadius)); 349a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mBackgroundRect.inset(3f, 3f); 350a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mBackgroundPaint.setStrokeWidth(TIME_LAPSE_ARC_WIDTH); 351a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND); 352a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mBackgroundPaint.setColor(TIME_LAPSE_ARC_COLOR); 353a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li 354a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li // Compute the start angle and sweep angle. 355a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li long timeDelta = SystemClock.uptimeMillis() - mRecordingStartTime; 356a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li long numberOfFrames = timeDelta / mTimeLapseInterval; 357248232e937007384328592e0c269b42cf03c6899Wu-cheng Li float sweepAngle; 358a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li if (numberOfFrames > mNumberOfFrames) { 359248232e937007384328592e0c269b42cf03c6899Wu-cheng Li // The arc just acrosses 0 degree. Draw a full circle so it 360248232e937007384328592e0c269b42cf03c6899Wu-cheng Li // looks better. 361248232e937007384328592e0c269b42cf03c6899Wu-cheng Li sweepAngle = 360; 362a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li mNumberOfFrames = numberOfFrames; 363a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li } else { 364248232e937007384328592e0c269b42cf03c6899Wu-cheng Li sweepAngle = timeDelta % mTimeLapseInterval * 360f / mTimeLapseInterval; 365a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li } 366a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li 367248232e937007384328592e0c269b42cf03c6899Wu-cheng Li canvas.drawArc(mBackgroundRect, 0, sweepAngle, false, mBackgroundPaint); 368248232e937007384328592e0c269b42cf03c6899Wu-cheng Li invalidate(); 369a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li } 370a18b115b025fe0c3b046348953946c8db07e12ceWu-cheng Li 37180715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li super.onDraw(canvas); 37280715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li } 37380715aae46e5a7a9aa378002301ba9d76f093776Wu-cheng Li 374823d57389b616091827059ca6401f675e416a53bWu-cheng Li // Scene mode may override other camera settings (ex: flash mode). 375823d57389b616091827059ca6401f675e416a53bWu-cheng Li public void overrideSettings(String key, String value) { 376823d57389b616091827059ca6401f675e416a53bWu-cheng Li int count = getChildCount(); 377823d57389b616091827059ca6401f675e416a53bWu-cheng Li for (int j = 1; j < count; j++) { 378823d57389b616091827059ca6401f675e416a53bWu-cheng Li View v = getChildAt(j); 379823d57389b616091827059ca6401f675e416a53bWu-cheng Li if (v instanceof IndicatorButton) { // skip the button of "other settings" 380823d57389b616091827059ca6401f675e416a53bWu-cheng Li IndicatorButton indicator = (IndicatorButton) v; 381823d57389b616091827059ca6401f675e416a53bWu-cheng Li if (key.equals(indicator.getKey())) { 382823d57389b616091827059ca6401f675e416a53bWu-cheng Li indicator.overrideSettings(value); 383b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan setEnabled(indicator, (value == null)); 384a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan break; 385823d57389b616091827059ca6401f675e416a53bWu-cheng Li } 386823d57389b616091827059ca6401f675e416a53bWu-cheng Li } 387823d57389b616091827059ca6401f675e416a53bWu-cheng Li } 388823d57389b616091827059ca6401f675e416a53bWu-cheng Li } 389d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan 390d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan // Sets/unsets highlight on the specified setting icon 391d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan private void setHighlight(int index, boolean enabled) { 392d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan if ((index < 0) || (index >= getChildCount() - 1)) return; 393d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan ImageView child = (ImageView) getChildAt(index + 1); 394d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan if (enabled) { 395d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan child.setColorFilter(HIGHLIGHT_COLOR); 396d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan } else { 397d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan child.clearColorFilter(); 398d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan } 399d09139b23bc06f8e0ecb90dd4048ab9ee374c253Hung-ying Tyan } 400e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan 401e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan @Override 402e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan public void setEnabled(boolean enabled) { 403e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan super.setEnabled(enabled); 404e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan int count = getChildCount(); 405b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan for (int i = 1; i < count; i++) { 406b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan setEnabled((ImageView) getChildAt(i), enabled); 407b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan } 408b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan } 409b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan 410b28ff297859deeacd9b70c0bb0299862a8606cbcHung-ying Tyan private void setEnabled(ImageView view, boolean enabled) { 41174d035db6dc5cc98fa3e53689e469155a35aec66Wu-cheng Li // Do not enable the button if it is overridden by scene mode. 41274d035db6dc5cc98fa3e53689e469155a35aec66Wu-cheng Li if ((view instanceof IndicatorButton) && ((IndicatorButton) view).isOverridden()) { 41374d035db6dc5cc98fa3e53689e469155a35aec66Wu-cheng Li enabled = false; 41474d035db6dc5cc98fa3e53689e469155a35aec66Wu-cheng Li } 41574d035db6dc5cc98fa3e53689e469155a35aec66Wu-cheng Li 416a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan // Don't do anything if state is not changed so not to interfere with 417a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan // the "highlight" state. 418a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan if (view.isEnabled() ^ enabled) { 419a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan view.setEnabled(enabled); 420a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan if (enabled) { 421a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan view.clearColorFilter(); 422a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan } else { 423a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan view.setColorFilter(DISABLED_COLOR); 424a25ee04fcb7be1a9aabc8bbccf044da70d4b5e88Hung-ying Tyan } 425e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan } 426e50d2553aeb9e55504697e2a72759e8f46ee2992Hung-ying Tyan } 4277341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4287341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li protected boolean addIndicator( 4297341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li Context context, PreferenceGroup group, String key) { 4307341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li IconListPreference pref = (IconListPreference) group.findPreference(key); 4317341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (pref == null) return false; 4327341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li IndicatorButton b = new IndicatorButton(context, pref); 4337341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li addView(b); 4347341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return true; 4357341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4367341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4377341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private void addOtherSettingIndicator(Context context) { 4387341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li ImageView b = new ImageView(context); 4397341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li b.setImageResource(R.drawable.ic_viewfinder_settings); 4407341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li b.setClickable(false); 4417341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li addView(b); 4427341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4437341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4447341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void initialize(Context context, PreferenceGroup group, 4457341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li String[] keys, boolean enableOtherSettings) { 4467341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li // Reset the variables and states. 4477341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li dismissSettingPopup(); 4487341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li removeIndicators(); 4497341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mOtherSettingsPopup = null; 4507341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mSelectedIndex = -1; 4517341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mPreferenceKeys = new ArrayList<String>(); 4527341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4537341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li // Initialize all variables and icons. 4547341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mPreferenceGroup = group; 4557341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li for (int i = 0; i < keys.length; i++) { 4567341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (addIndicator(context, group, keys[i])) { 4577341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mPreferenceKeys.add(keys[i]); 4587341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4597341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4607341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mBasicSettingPopups = new BasicSettingPopup[mPreferenceKeys.size()]; 4617341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4627341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (enableOtherSettings) { 4637341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li addOtherSettingIndicator(context); 4647341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4657341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li requestLayout(); 4667341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4677341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4687341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void onOtherSettingChanged() { 4697341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mListener != null) { 4707341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mListener.onSharedPreferenceChanged(); 4717341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4727341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4737341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4747341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void onRestorePreferencesClicked() { 4757341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mListener != null) { 4767341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mListener.onRestorePreferencesClicked(); 4777341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4787341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4797341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4807341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void onSettingChanged() { 4817341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li // Update indicator. 4827341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li IndicatorButton indicator = (IndicatorButton) getChildAt(mSelectedIndex + 1); 4837341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li indicator.reloadPreference(); 4847341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mListener != null) { 4857341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mListener.onSharedPreferenceChanged(); 4867341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4877341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 4887341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4897341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private void initializeSettingPopup(int index) { 4907341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li IconListPreference pref = (IconListPreference) 4917341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mPreferenceGroup.findPreference(mPreferenceKeys.get(index)); 4927341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 4937341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 4947341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li Context.LAYOUT_INFLATER_SERVICE); 4957341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li ViewGroup root = (ViewGroup) getRootView().findViewById(R.id.app_root); 4967341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li BasicSettingPopup popup = (BasicSettingPopup) inflater.inflate( 4977341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li R.layout.basic_setting_popup, root, false); 4987341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mBasicSettingPopups[index] = popup; 4997341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li popup.setSettingChangedListener(this); 5007341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li popup.initialize(pref); 5017341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li root.addView(popup); 5027341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5037341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5047341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li private void initializeOtherSettingPopup() { 5057341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 5067341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li Context.LAYOUT_INFLATER_SERVICE); 5077341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li ViewGroup root = (ViewGroup) getRootView().findViewById(R.id.app_root); 5087341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mOtherSettingsPopup = (OtherSettingsPopup) inflater.inflate( 5097341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li R.layout.other_setting_popup, root, false); 5107341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mOtherSettingsPopup.setOtherSettingChangedListener(this); 5117341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mOtherSettingsPopup.initialize(mPreferenceGroup); 5127341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li root.addView(mOtherSettingsPopup); 5137341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5147341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5154504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li private void showSettingPopup(int index) { 5164504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (index == mSelectedIndex) return; 5174504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li 5184504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (index < mBasicSettingPopups.length) { 5194504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (mBasicSettingPopups[index] == null) { 5204504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li initializeSettingPopup(index); 5217341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5227341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } else if (mOtherSettingsPopup == null) { 5237341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li initializeOtherSettingPopup(); 5247341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5257341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 52622898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li View popup; 52722898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li if (mPrevAnimatingView != null) mPrevAnimatingView.clearAnimation(); 5284504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li if (index == mBasicSettingPopups.length) { 52922898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup = mOtherSettingsPopup; 5307341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } else { 53122898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup = mBasicSettingPopups[index]; 5327341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 53322898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup.startAnimation(mFadeIn); 53422898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup.setVisibility(View.VISIBLE); 53522898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li mPrevAnimatingView = popup; 5364504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li setHighlight(index, true); 5374504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li mSelectedIndex = index; 5384504e5b41a0f647ef3e16b1134e130fe3678aebfWu-cheng Li invalidate(); 5397341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5407341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5417341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public boolean dismissSettingPopup() { 5427341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mSelectedIndex >= 0) { 54322898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li View popup; 54422898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li if (mPrevAnimatingView != null) mPrevAnimatingView.clearAnimation(); 5457341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mSelectedIndex == mBasicSettingPopups.length) { 54622898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup = mOtherSettingsPopup; 5477341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } else { 54822898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup = mBasicSettingPopups[mSelectedIndex]; 5497341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 55022898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup.startAnimation(mFadeOut); 55122898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li popup.setVisibility(View.INVISIBLE); 55222898716834e5c08854a8ee1e71dc81a1ea8355eWu-cheng Li mPrevAnimatingView = popup; 5537341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li setHighlight(mSelectedIndex, false); 5547341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mSelectedIndex = -1; 5557341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li invalidate(); 5567341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return true; 5577341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5587341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return false; 5597341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5607341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5617341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public View getActivePopupWindow() { 5627341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mSelectedIndex >= 0) { 5637341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mSelectedIndex == mBasicSettingPopups.length) { 5647341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return mOtherSettingsPopup; 5657341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } else { 5667341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return mBasicSettingPopups[mSelectedIndex]; 5677341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5687341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } else { 5697341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li return null; 5707341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5717341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5727341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5737341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li // Scene mode may override other camera settings (ex: flash mode). 5747341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public void overrideSettings(final String ... keyvalues) { 5757341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (keyvalues.length % 2 != 0) { 5767341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li throw new IllegalArgumentException(); 5777341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5787341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5797341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li if (mOtherSettingsPopup == null) { 5807341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li initializeOtherSettingPopup(); 5817341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5827341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li 5837341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li for (int i = 0; i < keyvalues.length; i += 2) { 5847341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li String key = keyvalues[i]; 5857341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li String value = keyvalues[i + 1]; 5867341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li overrideSettings(key, value); 5877341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li mOtherSettingsPopup.overrideSettings(key, value); 5887341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5897341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li } 5906f2283fbf049ad1f9870a86474af295604d95600Wu-cheng Li} 591