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; 18 19 import com.android.camera.ui.PopupManager; 20 import com.android.camera.ui.RotateImageView; 21 22 import android.content.Context; 23 import android.graphics.PorterDuff; 24 import android.graphics.drawable.Drawable; 25 import android.util.AttributeSet; 26 import android.util.Log; 27 import android.view.View; 28 import android.view.animation.Animation; 29 import android.view.animation.Animation.AnimationListener; 30 import android.view.animation.AnimationUtils; 31 import android.widget.ImageView; 32 import android.widget.RelativeLayout; 33 34 /** 35 * A widget that includes three mode selections {@code RotateImageView}'s and 36 * a current mode indicator. 37 */ 38 public class ModePicker extends RelativeLayout implements View.OnClickListener, 39 PopupManager.OnOtherPopupShowedListener { 40 public static final int MODE_CAMERA = 0; 41 public static final int MODE_VIDEO = 1; 42 public static final int MODE_PANORAMA = 2; 43 44 private static final String TAG = "ModePicker"; 45 // Total mode number 46 private static final int MODE_NUM = 3; 47 48 /** A callback to be called when the user wants to switch activity. */ 49 public interface OnModeChangeListener { 50 // Returns true if the listener agrees that the mode can be changed. onModeChanged(int newMode)51 public boolean onModeChanged(int newMode); 52 } 53 54 private final int DISABLED_COLOR; 55 private final int CURRENT_MODE_BACKGROUND; 56 57 private OnModeChangeListener mListener; 58 private View mModeSelectionFrame; 59 private RotateImageView mModeSelectionIcon[]; 60 private View mCurrentModeFrame; 61 private RotateImageView mCurrentModeIcon[]; 62 private View mCurrentModeBar; 63 private boolean mSelectionEnabled; 64 65 66 private int mCurrentMode = 0; 67 private Animation mFadeIn, mFadeOut; 68 ModePicker(Context context, AttributeSet attrs)69 public ModePicker(Context context, AttributeSet attrs) { 70 super(context, attrs); 71 DISABLED_COLOR = context.getResources().getColor(R.color.icon_disabled_color); 72 CURRENT_MODE_BACKGROUND = R.drawable.btn_mode_background; 73 mFadeIn = AnimationUtils.loadAnimation( 74 context, R.anim.mode_selection_fade_in); 75 mFadeOut = AnimationUtils.loadAnimation( 76 context, R.anim.mode_selection_fade_out); 77 mFadeOut.setAnimationListener(mAnimationListener); 78 PopupManager.getInstance(context).setOnOtherPopupShowedListener(this); 79 } 80 onFinishInflate()81 protected void onFinishInflate() { 82 super.onFinishInflate(); 83 84 mModeSelectionFrame = findViewById(R.id.mode_selection); 85 mModeSelectionIcon = new RotateImageView[MODE_NUM]; 86 mModeSelectionIcon[MODE_PANORAMA] = 87 (RotateImageView) findViewById(R.id.mode_panorama); 88 mModeSelectionIcon[MODE_VIDEO] = 89 (RotateImageView) findViewById(R.id.mode_video); 90 mModeSelectionIcon[MODE_CAMERA] = 91 (RotateImageView) findViewById(R.id.mode_camera); 92 93 // The current mode frame is for Phone UI only. 94 mCurrentModeFrame = findViewById(R.id.current_mode); 95 if (mCurrentModeFrame != null) { 96 mCurrentModeIcon = new RotateImageView[MODE_NUM]; 97 mCurrentModeIcon[0] = (RotateImageView) findViewById(R.id.mode_0); 98 mCurrentModeIcon[1] = (RotateImageView) findViewById(R.id.mode_1); 99 mCurrentModeIcon[2] = (RotateImageView) findViewById(R.id.mode_2); 100 } else { 101 // current_mode_bar is only for tablet. 102 mCurrentModeBar = findViewById(R.id.current_mode_bar); 103 enableModeSelection(true); 104 } 105 registerOnClickListener(); 106 } 107 registerOnClickListener()108 private void registerOnClickListener() { 109 if (mCurrentModeFrame != null) { 110 mCurrentModeFrame.setOnClickListener(this); 111 } 112 for (int i = 0; i < MODE_NUM; ++i) { 113 mModeSelectionIcon[i].setOnClickListener(this); 114 } 115 } 116 117 @Override onOtherPopupShowed()118 public void onOtherPopupShowed() { 119 if (mSelectionEnabled) enableModeSelection(false); 120 } 121 122 private AnimationListener mAnimationListener = new AnimationListener() { 123 public void onAnimationEnd(Animation animation) { 124 changeToSelectedMode(); 125 mCurrentModeFrame.setVisibility(View.VISIBLE); 126 mModeSelectionFrame.setVisibility(View.GONE); 127 } 128 129 public void onAnimationRepeat(Animation animation) { 130 } 131 132 public void onAnimationStart(Animation animation) { 133 } 134 }; 135 enableModeSelection(boolean enabled)136 private void enableModeSelection(boolean enabled) { 137 if (mCurrentModeFrame != null) { 138 mSelectionEnabled = enabled; 139 // Animation Effect is applied on Phone UI only. 140 mModeSelectionFrame.startAnimation(enabled ? mFadeIn : mFadeOut); 141 if (enabled) { 142 mModeSelectionFrame.setVisibility(View.VISIBLE); 143 mCurrentModeFrame.setVisibility(View.GONE); 144 } 145 } 146 updateModeState(); 147 } 148 changeToSelectedMode()149 private void changeToSelectedMode() { 150 if (mListener != null) { 151 if (mListener.onModeChanged(mCurrentMode)) { 152 Log.e(TAG, "failed:onModeChanged:" + mCurrentMode); 153 } 154 } 155 } 156 onClick(View view)157 public void onClick(View view) { 158 if (view == mCurrentModeFrame) { 159 PopupManager.getInstance(getContext()).notifyShowPopup(this); 160 enableModeSelection(true); 161 } else { 162 // Set the selected mode as the current one and switch to it. 163 for (int i = 0; i < MODE_NUM; ++i) { 164 if (view == mModeSelectionIcon[i] && (mCurrentMode != i)) { 165 setCurrentMode(i); 166 break; 167 } 168 } 169 if (mCurrentModeBar == null) { 170 enableModeSelection(false); 171 } else { 172 changeToSelectedMode(); 173 } 174 } 175 } 176 setOnModeChangeListener(OnModeChangeListener listener)177 public void setOnModeChangeListener(OnModeChangeListener listener) { 178 mListener = listener; 179 } 180 setCurrentMode(int mode)181 public void setCurrentMode(int mode) { 182 mCurrentMode = mode; 183 updateModeState(); 184 } 185 onModeChanged(int mode)186 public boolean onModeChanged(int mode) { 187 setCurrentMode(mode); 188 return true; 189 } 190 setDegree(int degree)191 public void setDegree(int degree) { 192 for (int i = 0; i < MODE_NUM; ++i) { 193 mModeSelectionIcon[i].setDegree(degree); 194 if (mCurrentModeFrame != null) { 195 mCurrentModeIcon[i].setDegree(degree); 196 } 197 } 198 } 199 200 @Override setEnabled(boolean enabled)201 public void setEnabled(boolean enabled) { 202 super.setEnabled(enabled); 203 204 // Enable or disable the frames. 205 if (mCurrentModeFrame != null) mCurrentModeFrame.setEnabled(enabled); 206 mModeSelectionFrame.setEnabled(enabled); 207 208 // Enable or disable the icons. 209 for (int i = 0; i < MODE_NUM; ++i) { 210 mModeSelectionIcon[i].setEnabled(enabled); 211 if (mCurrentModeFrame != null) mCurrentModeIcon[i].setEnabled(enabled); 212 } 213 if (enabled) updateModeState(); 214 } 215 highlightView(ImageView view, boolean enabled)216 private void highlightView(ImageView view, boolean enabled) { 217 if (enabled) { 218 view.clearColorFilter(); 219 } else { 220 view.setColorFilter(DISABLED_COLOR, PorterDuff.Mode.SRC_ATOP); 221 } 222 } 223 updateModeState()224 private void updateModeState() { 225 // Grey-out the unselected icons. 226 for (int i = 0; i < MODE_NUM; ++i) { 227 highlightView(mModeSelectionIcon[i], (i == mCurrentMode)); 228 } 229 // Update the current mode icons on the Phone UI. The selected mode 230 // should be in the center of the current mode icon bar. 231 if (mCurrentModeFrame != null) { 232 for (int i = 0, j = 0; i < MODE_NUM; ++i) { 233 int target; 234 if (i == 1) { 235 // The second icon is always the selected mode. 236 target = mCurrentMode; 237 } else { 238 // Set the icons in order of camera, video and panorama. 239 if (j == mCurrentMode) j++; 240 target = j++; 241 } 242 mCurrentModeIcon[i].setImageDrawable( 243 mModeSelectionIcon[target].getDrawable()); 244 } 245 } 246 } 247 248 @Override onLayout( boolean changed, int left, int top, int right, int bottom)249 protected void onLayout( 250 boolean changed, int left, int top, int right, int bottom) { 251 super.onLayout(changed, left, top, right, bottom); 252 // Layout the current mode indicator bar. 253 if (mCurrentModeBar != null) { 254 int viewWidth = mModeSelectionIcon[MODE_CAMERA].getWidth(); 255 int iconWidth = ((ImageView) mModeSelectionIcon[MODE_CAMERA]) 256 .getDrawable().getIntrinsicWidth(); 257 int padding = (viewWidth - iconWidth) / 2; 258 int l = mModeSelectionFrame.getLeft() + mCurrentMode * viewWidth; 259 mCurrentModeBar.layout((l + padding), 260 (bottom - top - mCurrentModeBar.getHeight()), 261 (l + padding + iconWidth), 262 (bottom - top)); 263 } 264 } 265 } 266