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