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