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