ModePicker.java revision 20ff6a12d36dd928e6ccfb96aebf9f6481d15697
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.Util;
20import com.android.camera.ui.RotateImageView;
21
22import android.content.Context;
23import android.graphics.Color;
24import android.graphics.PorterDuff;
25import android.graphics.drawable.Drawable;
26import android.util.AttributeSet;
27import android.view.View;
28import android.view.animation.Animation;
29import android.view.animation.Animation.AnimationListener;
30import android.view.animation.AnimationUtils;
31import android.widget.ImageView;
32import android.widget.RelativeLayout;
33
34/**
35 * A widget that includes three mode selections {@code RotateImageView}'s and
36 * a current mode indicator.
37 */
38public class ModePicker extends RelativeLayout implements View.OnClickListener {
39    public static final int MODE_CAMERA = 0;
40    public static final int MODE_VIDEO = 1;
41    public static final int MODE_PANORAMA = 2;
42
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    private View mSelectedView;
62
63    private int mCurrentMode = -1;
64    private Animation mFadeIn, mFadeOut;
65
66    public ModePicker(Context context, AttributeSet attrs) {
67        super(context, attrs);
68        DISABLED_COLOR = context.getResources().getColor(R.color.icon_disabled_color);
69        CURRENT_MODE_BACKGROUND = R.drawable.btn_mode_background;
70        mFadeIn = AnimationUtils.loadAnimation(
71                context, R.anim.mode_selection_fade_in);
72        mFadeOut = AnimationUtils.loadAnimation(
73                context, R.anim.mode_selection_fade_out);
74        mFadeOut.setAnimationListener(mAnimationListener);
75    }
76
77    protected void onFinishInflate() {
78        super.onFinishInflate();
79
80        mModeSelectionFrame = findViewById(R.id.mode_selection);
81        mModeSelectionIcon = new RotateImageView[MODE_NUM];
82        mModeSelectionIcon[MODE_PANORAMA] =
83                (RotateImageView) findViewById(R.id.mode_panorama);
84        mModeSelectionIcon[MODE_VIDEO] =
85                (RotateImageView) findViewById(R.id.mode_video);
86        mModeSelectionIcon[MODE_CAMERA] =
87                (RotateImageView) findViewById(R.id.mode_camera);
88
89        // The current mode frame is for Phone UI only.
90        mCurrentModeFrame = findViewById(R.id.current_mode);
91        if (mCurrentModeFrame != null) {
92            mCurrentModeFrame.setOnClickListener(this);
93            mCurrentModeIcon = new RotateImageView[MODE_NUM];
94            mCurrentModeIcon[0] = (RotateImageView) findViewById(R.id.mode_0);
95            mCurrentModeIcon[1] = (RotateImageView) findViewById(R.id.mode_1);
96            mCurrentModeIcon[2] = (RotateImageView) findViewById(R.id.mode_2);
97        } else {
98            // current_mode_bar is only for tablet.
99            mCurrentModeBar = findViewById(R.id.current_mode_bar);
100            enableModeSelection(true);
101        }
102    }
103
104    private AnimationListener mAnimationListener = new AnimationListener() {
105        public void onAnimationEnd(Animation animation) {
106            changeToSelectedMode();
107            mCurrentModeFrame.setVisibility(View.VISIBLE);
108            mModeSelectionFrame.setVisibility(View.GONE);
109        }
110
111        public void onAnimationRepeat(Animation animation) {
112        }
113
114        public void onAnimationStart(Animation animation) {
115        }
116    };
117
118    private void enableModeSelection(boolean enabled) {
119        if (mCurrentModeFrame != null) {
120            // Animation Effect is applied on Phone UI only.
121            mModeSelectionFrame.startAnimation(enabled ? mFadeIn : mFadeOut);
122            if (enabled) {
123                mModeSelectionFrame.setVisibility(View.VISIBLE);
124                mCurrentModeFrame.setVisibility(View.GONE);
125            }
126            mCurrentModeFrame.setOnClickListener(enabled ? null : this);
127        }
128        for (int i = 0; i < MODE_NUM; ++i) {
129            mModeSelectionIcon[i].setOnClickListener(enabled ? this : null);
130        }
131        updateModeState();
132    }
133
134    private void changeToSelectedMode() {
135        for (int i = 0; i < MODE_NUM; ++i) {
136            if (mSelectedView == mModeSelectionIcon[i]) {
137                setCurrentMode(i);
138                return;
139            }
140        }
141    }
142
143    public void onClick(View view) {
144        if (view == mCurrentModeFrame) {
145            enableModeSelection(true);
146        } else {
147            // The view in selection menu is clicked.
148            mSelectedView = view;
149            if (mCurrentModeBar == null) {
150                enableModeSelection(false);
151            } else {
152                changeToSelectedMode();
153            }
154        }
155    }
156
157    private void setMode(int mode) {
158        for (int i = 0; i < MODE_NUM; ++i) {
159            mModeSelectionIcon[i].setSelected(mode == i);
160        }
161    }
162
163    public void setOnModeChangeListener(OnModeChangeListener listener) {
164        mListener = listener;
165    }
166
167    public void setCurrentMode(int mode) {
168        if (mCurrentMode == mode) return;
169        setMode(mode);
170        tryToSetMode(mode);
171    }
172
173    private void tryToSetMode(int mode) {
174        if (mListener != null) {
175            if (!mListener.onModeChanged(mode)) {
176                setMode(mCurrentMode);
177                return;
178            }
179        }
180        mCurrentMode = mode;
181        updateModeState();
182    }
183
184    public boolean onModeChanged(int mode) {
185        setCurrentMode(mode);
186        return true;
187    }
188
189    public void setDegree(int degree) {
190        for (int i = 0; i < MODE_NUM; ++i) {
191            mModeSelectionIcon[i].setDegree(degree);
192            if (mCurrentModeFrame != null) {
193                mCurrentModeIcon[i].setDegree(degree);
194            }
195        }
196    }
197
198    @Override
199    public void setEnabled(boolean enabled) {
200        super.setEnabled(enabled);
201
202        // Enable or disable the frames.
203        if (mCurrentModeFrame != null) mCurrentModeFrame.setEnabled(enabled);
204        mModeSelectionFrame.setEnabled(enabled);
205
206        // Enable or disable the icons.
207        for (int i = 0; i < MODE_NUM; ++i) {
208            mModeSelectionIcon[i].setEnabled(enabled);
209            if (mCurrentModeFrame != null) mCurrentModeIcon[i].setEnabled(enabled);
210        }
211        if (enabled) updateModeState();
212    }
213
214    private void highlightView(View view, boolean enabled) {
215        Drawable drawable = ((ImageView) view).getDrawable();
216        if (enabled) {
217            drawable.clearColorFilter();
218        } else {
219            drawable.setColorFilter(DISABLED_COLOR, PorterDuff.Mode.SRC_ATOP);
220        }
221        requestLayout();
222    }
223
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
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