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