blob: ba205a8bb450cfcaa54639aa9ee188168b6b5281 [file] [log] [blame]
Chih-Chung Chang91acfc92009-07-06 15:37:24 +08001/*
2 * Copyright (C) 2009 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
Owen Lindad4b182009-06-11 16:02:29 -070017package com.android.camera;
18
19import android.content.Context;
20import android.graphics.Canvas;
21import android.graphics.drawable.Drawable;
22import android.util.AttributeSet;
Owen Line239acc2009-06-23 22:18:20 -070023import android.view.MotionEvent;
Chih-Chung Chang781f55b2009-08-10 17:00:52 +080024import android.view.View;
Owen Line239acc2009-06-23 22:18:20 -070025import android.view.animation.AnimationUtils;
Owen Lindad4b182009-06-11 16:02:29 -070026import android.widget.ImageView;
27
Chih-Chung Chang781f55b2009-08-10 17:00:52 +080028public class Switcher extends ImageView implements View.OnTouchListener {
Owen Line594b192009-08-13 18:04:45 +080029
30 @SuppressWarnings("unused")
Chih-Chung Changd918cfa2009-07-13 13:11:52 +080031 private static final String TAG = "Switcher";
32
Owen Line239acc2009-06-23 22:18:20 -070033 public interface OnSwitchListener {
Chih-Chung Changd918cfa2009-07-13 13:11:52 +080034 // Returns true if the listener agrees that the switch can be changed.
35 public boolean onSwitchChanged(Switcher source, boolean onOff);
Owen Line239acc2009-06-23 22:18:20 -070036 }
37
38 private static final int ANIMATION_SPEED = 200;
39 private static final long NO_ANIMATION = -1;
Owen Lindad4b182009-06-11 16:02:29 -070040
41 private boolean mSwitch = false;
Owen Line239acc2009-06-23 22:18:20 -070042 private int mPosition = 0;
43 private long mAnimationStartTime = 0;
44 private OnSwitchListener mListener;
Owen Lindad4b182009-06-11 16:02:29 -070045
46 public Switcher(Context context, AttributeSet attrs) {
47 super(context, attrs);
48 }
49
50 public void setSwitch(boolean onOff) {
Chih-Chung Chang781f55b2009-08-10 17:00:52 +080051 if (mSwitch == onOff) return;
52 mSwitch = onOff;
53 invalidate();
54 }
55
56 // Try to change the switch position. (The client can veto it.)
57 private void tryToSetSwitch(boolean onOff) {
Chih-Chung Changd918cfa2009-07-13 13:11:52 +080058 try {
59 if (mSwitch == onOff) return;
60
61 if (mListener != null) {
62 if (!mListener.onSwitchChanged(this, onOff)) {
63 return;
64 }
65 }
66
67 mSwitch = onOff;
68 } finally {
69 startParkingAnimation();
70 }
Owen Line239acc2009-06-23 22:18:20 -070071 }
72
73 public void setOnSwitchListener(OnSwitchListener listener) {
74 mListener = listener;
75 }
76
77 @Override
78 public boolean onTouchEvent(MotionEvent event) {
79 if (!isEnabled()) return false;
80
81 final int available = getHeight() - mPaddingTop - mPaddingBottom
82 - getDrawable().getIntrinsicHeight();
83
84 switch (event.getAction()) {
85 case MotionEvent.ACTION_DOWN:
86 mAnimationStartTime = NO_ANIMATION;
87 setPressed(true);
88 trackTouchEvent(event);
89 break;
90
91 case MotionEvent.ACTION_MOVE:
92 trackTouchEvent(event);
93 break;
94
95 case MotionEvent.ACTION_UP:
96 trackTouchEvent(event);
Chih-Chung Chang781f55b2009-08-10 17:00:52 +080097 tryToSetSwitch(mPosition >= available / 2);
Owen Line239acc2009-06-23 22:18:20 -070098 setPressed(false);
99 break;
100
101 case MotionEvent.ACTION_CANCEL:
Chih-Chung Chang781f55b2009-08-10 17:00:52 +0800102 tryToSetSwitch(mSwitch);
Owen Line239acc2009-06-23 22:18:20 -0700103 setPressed(false);
Owen Line239acc2009-06-23 22:18:20 -0700104 break;
105 }
106 return true;
107 }
108
109 private void startParkingAnimation() {
Owen Line239acc2009-06-23 22:18:20 -0700110 mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis();
111 }
112
113 private void trackTouchEvent(MotionEvent event) {
114 Drawable drawable = getDrawable();
115 int drawableHeight = drawable.getIntrinsicHeight();
116 final int height = getHeight();
117 final int available = height - mPaddingTop - mPaddingBottom
118 - drawableHeight;
119 int x = (int) event.getY();
120 mPosition = x - mPaddingTop - drawableHeight / 2;
121 if (mPosition < 0) mPosition = 0;
122 if (mPosition > available) mPosition = available;
123 invalidate();
Owen Lindad4b182009-06-11 16:02:29 -0700124 }
125
126 @Override
127 protected void onDraw(Canvas canvas) {
128
129 Drawable drawable = getDrawable();
130 int drawableHeight = drawable.getIntrinsicHeight();
131 int drawableWidth = drawable.getIntrinsicWidth();
132
Owen Lindad4b182009-06-11 16:02:29 -0700133 if (drawableWidth == 0 || drawableHeight == 0) {
134 return; // nothing to draw (empty bounds)
135 }
136
Owen Line239acc2009-06-23 22:18:20 -0700137 if (mAnimationStartTime != NO_ANIMATION) {
138 final int available = getHeight() - mPaddingTop - mPaddingBottom
139 - drawableHeight;
140 long time = AnimationUtils.currentAnimationTimeMillis();
141 long deltaTime = time - mAnimationStartTime;
142 mPosition += ANIMATION_SPEED
143 * (mSwitch ? deltaTime : -deltaTime) / 1000;
144 mAnimationStartTime = time;
145 if (mPosition < 0) mPosition = 0;
146 if (mPosition > available) mPosition = available;
147 if (mPosition != 0 && mPosition != available) {
148 postInvalidate();
149 } else {
150 mAnimationStartTime = NO_ANIMATION;
151 }
152 }
153
154 int offsetTop = mPaddingTop + mPosition;
Owen Lindad4b182009-06-11 16:02:29 -0700155 int offsetLeft = (getWidth()
156 - drawableWidth - mPaddingLeft - mPaddingRight) / 2;
157 int saveCount = canvas.getSaveCount();
158 canvas.save();
159 canvas.translate(offsetLeft, offsetTop);
160 drawable.draw(canvas);
161 canvas.restoreToCount(saveCount);
162 }
163
Chih-Chung Chang781f55b2009-08-10 17:00:52 +0800164 // Consume the touch events for the specified view.
165 public void addTouchView(View v) {
166 v.setOnTouchListener(this);
167 }
168
169 // This implements View.OnTouchListener so we intercept the touch events
170 // and pass them to ourselves.
171 public boolean onTouch(View v, MotionEvent event) {
172 onTouchEvent(event);
173 return true;
174 }
Owen Lindad4b182009-06-11 16:02:29 -0700175}