1 /* 2 * Copyright (C) 2011 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.ui; 18 19 import android.content.Context; 20 import android.os.Handler; 21 import android.os.Message; 22 import android.view.MotionEvent; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.view.animation.Animation; 26 import android.view.animation.AnimationUtils; 27 import android.widget.ImageView; 28 29 import com.android.camera.R; 30 31 // This is an indicator button and pressing it opens a popup window. Ex: flash or other settings. 32 public abstract class AbstractIndicatorButton extends RotateImageView implements 33 PopupManager.OnOtherPopupShowedListener { 34 @SuppressWarnings("unused") 35 private static final String TAG = "AbstractIndicatorButton"; 36 protected Animation mFadeIn, mFadeOut; 37 protected final int HIGHLIGHT_COLOR; 38 protected AbstractSettingPopup mPopup; 39 protected Handler mHandler = new MainHandler(); 40 private final int MSG_DISMISS_POPUP = 0; 41 private IndicatorChangeListener mListener; 42 43 public static interface IndicatorChangeListener { onShowIndicator(View view, boolean showed)44 public void onShowIndicator(View view, boolean showed); 45 } 46 AbstractIndicatorButton(Context context)47 public AbstractIndicatorButton(Context context) { 48 super(context); 49 mFadeIn = AnimationUtils.loadAnimation(context, R.anim.setting_popup_grow_fade_in); 50 mFadeOut = AnimationUtils.loadAnimation(context, R.anim.setting_popup_shrink_fade_out); 51 HIGHLIGHT_COLOR = context.getResources().getColor(R.color.review_control_pressed_color); 52 setScaleType(ImageView.ScaleType.CENTER); 53 PopupManager.getInstance(context).setOnOtherPopupShowedListener(this); 54 // Set the click listener to help the comprehension of the accessibility. 55 setClickable(true); 56 } 57 58 @Override onOtherPopupShowed()59 public void onOtherPopupShowed() { 60 dismissPopup(); 61 } 62 setIndicatorChangeListener(IndicatorChangeListener listener)63 public void setIndicatorChangeListener(IndicatorChangeListener listener) { 64 mListener = listener; 65 } 66 67 // Whether scene mode affects this indicator and it cannot be changed. isOverridden()68 public boolean isOverridden() { 69 return false; 70 } 71 72 // Scene mode may override other settings like flash, white-balance, and focus. overrideSettings(final String ... keyvalues)73 abstract public void overrideSettings(final String ... keyvalues); 74 75 @Override onTouchEvent(MotionEvent ev)76 public boolean onTouchEvent(MotionEvent ev) { 77 if (!isEnabled()) return false; 78 79 int action = ev.getAction(); 80 if (action == MotionEvent.ACTION_DOWN && !isOverridden()) { 81 if (mPopup == null || mPopup.getVisibility() != View.VISIBLE) { 82 showPopup(); 83 PopupManager.getInstance(getContext()).notifyShowPopup(this); 84 } else { 85 dismissPopup(); 86 } 87 return true; 88 } else if (action == MotionEvent.ACTION_CANCEL) { 89 dismissPopup(); 90 return true; 91 } 92 return false; 93 } 94 95 @Override setEnabled(boolean enabled)96 public void setEnabled(boolean enabled) { 97 // Do not enable the button if it is overridden by scene mode. 98 if (isOverridden()) { 99 enabled = false; 100 } 101 102 // Don't do anything if state is not changed so not to interfere with 103 // the "highlight" state. 104 if (isEnabled() ^ enabled) { 105 super.setEnabled(enabled); 106 } 107 } 108 109 @Override setOrientation(int orientation, boolean animation)110 public void setOrientation(int orientation, boolean animation) { 111 super.setOrientation(orientation, animation); 112 if (mPopup != null) { 113 mPopup.setOrientation(orientation, animation); 114 } 115 } 116 initializePopup()117 abstract protected void initializePopup(); 118 showPopup()119 private void showPopup() { 120 setPressed(true); 121 mHandler.removeMessages(MSG_DISMISS_POPUP); 122 if (mPopup == null) initializePopup(); 123 124 mPopup.setVisibility(View.VISIBLE); 125 mPopup.setOrientation(getDegree(), false); 126 mPopup.clearAnimation(); 127 mPopup.startAnimation(mFadeIn); 128 if (mListener != null) mListener.onShowIndicator(this, true); 129 } 130 dismissPopup()131 public boolean dismissPopup() { 132 setPressed(false); 133 mHandler.removeMessages(MSG_DISMISS_POPUP); 134 if (mPopup != null && mPopup.getVisibility() == View.VISIBLE) { 135 mPopup.clearAnimation(); 136 mPopup.startAnimation(mFadeOut); 137 mPopup.setVisibility(View.GONE); 138 if (mListener != null) mListener.onShowIndicator(this, false); 139 invalidate(); 140 // Indicator wheel needs to update the highlight indicator if this 141 // is dismissed by MSG_DISMISS_POPUP. 142 ((View) getParent()).invalidate(); 143 return true; 144 } 145 return false; 146 } 147 getPopupWindow()148 public AbstractSettingPopup getPopupWindow() { 149 if (mPopup != null && mPopup.getVisibility() == View.VISIBLE) { 150 return mPopup; 151 } else { 152 return null; 153 } 154 } 155 removePopupWindow()156 public void removePopupWindow() { 157 if (mPopup != null) { 158 ViewGroup root = (ViewGroup) getRootView().findViewById(R.id.frame_layout); 159 root.removeView(mPopup); 160 mPopup = null; 161 } 162 } 163 reloadPreference()164 public void reloadPreference() { 165 if (mPopup != null) mPopup.reloadPreference(); 166 } 167 dismissPopupDelayed()168 protected void dismissPopupDelayed() { 169 if (!mHandler.hasMessages(MSG_DISMISS_POPUP)) { 170 mHandler.sendEmptyMessage(MSG_DISMISS_POPUP); 171 } 172 } 173 174 private class MainHandler extends Handler { 175 @Override handleMessage(Message msg)176 public void handleMessage(Message msg) { 177 switch (msg.what) { 178 case MSG_DISMISS_POPUP: 179 dismissPopup(); 180 break; 181 } 182 } 183 } 184 } 185