• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.camera;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.drawable.Drawable;
22 import android.util.AttributeSet;
23 import android.util.Log;
24 import android.view.MotionEvent;
25 import android.view.View;
26 import android.view.animation.AnimationUtils;
27 import android.widget.ImageView;
28 
29 /**
30  * A widget which switchs between the {@code Camera} and the {@code VideoCamera}
31  * activities.
32  */
33 public class Switcher extends ImageView implements View.OnTouchListener {
34 
35     @SuppressWarnings("unused")
36     private static final String TAG = "Switcher";
37 
38     /** A callback to be called when the user wants to switch activity. */
39     public interface OnSwitchListener {
40         // Returns true if the listener agrees that the switch can be changed.
onSwitchChanged(Switcher source, boolean onOff)41         public boolean onSwitchChanged(Switcher source, boolean onOff);
42     }
43 
44     private static final int ANIMATION_SPEED = 200;
45     private static final long NO_ANIMATION = -1;
46 
47     private boolean mSwitch = false;
48     private int mPosition = 0;
49     private long mAnimationStartTime = NO_ANIMATION;
50     private int mAnimationStartPosition;
51     private OnSwitchListener mListener;
52 
Switcher(Context context, AttributeSet attrs)53     public Switcher(Context context, AttributeSet attrs) {
54         super(context, attrs);
55     }
56 
setSwitch(boolean onOff)57     public void setSwitch(boolean onOff) {
58         if (mSwitch == onOff) return;
59         mSwitch = onOff;
60         invalidate();
61     }
62 
63     // Try to change the switch position. (The client can veto it.)
tryToSetSwitch(boolean onOff)64     private void tryToSetSwitch(boolean onOff) {
65         try {
66             if (mSwitch == onOff) return;
67 
68             if (mListener != null) {
69                 if (!mListener.onSwitchChanged(this, onOff)) {
70                     return;
71                 }
72             }
73 
74             mSwitch = onOff;
75         } finally {
76             startParkingAnimation();
77         }
78     }
79 
setOnSwitchListener(OnSwitchListener listener)80     public void setOnSwitchListener(OnSwitchListener listener) {
81         mListener = listener;
82     }
83 
84     @Override
onTouchEvent(MotionEvent event)85     public boolean onTouchEvent(MotionEvent event) {
86         if (!isEnabled()) return false;
87 
88         final int available = getHeight() - getPaddingTop() - getPaddingBottom()
89                 - getDrawable().getIntrinsicHeight();
90 
91         switch (event.getAction()) {
92             case MotionEvent.ACTION_DOWN:
93                 mAnimationStartTime = NO_ANIMATION;
94                 setPressed(true);
95                 trackTouchEvent(event);
96                 break;
97 
98             case MotionEvent.ACTION_MOVE:
99                 trackTouchEvent(event);
100                 break;
101 
102             case MotionEvent.ACTION_UP:
103                 trackTouchEvent(event);
104                 tryToSetSwitch(mPosition >= available / 2);
105                 setPressed(false);
106                 break;
107 
108             case MotionEvent.ACTION_CANCEL:
109                 tryToSetSwitch(mSwitch);
110                 setPressed(false);
111                 break;
112         }
113         return true;
114     }
115 
startParkingAnimation()116     private void startParkingAnimation() {
117         mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis();
118         mAnimationStartPosition = mPosition;
119     }
120 
trackTouchEvent(MotionEvent event)121     private void trackTouchEvent(MotionEvent event) {
122         Drawable drawable = getDrawable();
123         int drawableHeight = drawable.getIntrinsicHeight();
124         final int height = getHeight();
125         final int available = height - getPaddingTop() - getPaddingBottom()
126                 - drawableHeight;
127         int x = (int) event.getY();
128         mPosition = x - getPaddingTop() - drawableHeight / 2;
129         if (mPosition < 0) mPosition = 0;
130         if (mPosition > available) mPosition = available;
131         invalidate();
132     }
133 
134     @Override
onDraw(Canvas canvas)135     protected void onDraw(Canvas canvas) {
136 
137         Drawable drawable = getDrawable();
138         int drawableHeight = drawable.getIntrinsicHeight();
139         int drawableWidth = drawable.getIntrinsicWidth();
140 
141         if (drawableWidth == 0 || drawableHeight == 0) {
142             return;     // nothing to draw (empty bounds)
143         }
144 
145         final int available = getHeight() - getPaddingTop()
146                 - getPaddingBottom() - drawableHeight;
147         if (mAnimationStartTime != NO_ANIMATION) {
148             long time = AnimationUtils.currentAnimationTimeMillis();
149             int deltaTime = (int) (time - mAnimationStartTime);
150             mPosition = mAnimationStartPosition +
151                     ANIMATION_SPEED * (mSwitch ? deltaTime : -deltaTime) / 1000;
152             if (mPosition < 0) mPosition = 0;
153             if (mPosition > available) mPosition = available;
154             boolean done = (mPosition == (mSwitch ? available : 0));
155             if (!done) {
156                 invalidate();
157             } else {
158                 mAnimationStartTime = NO_ANIMATION;
159             }
160         } else if (!isPressed()){
161             mPosition = mSwitch ? available : 0;
162         }
163         int offsetTop = getPaddingTop() + mPosition;
164         int offsetLeft = (getWidth()
165                 - drawableWidth - getPaddingLeft() - getPaddingRight()) / 2;
166         int saveCount = canvas.getSaveCount();
167         canvas.save();
168         canvas.translate(offsetLeft, offsetTop);
169         drawable.draw(canvas);
170         canvas.restoreToCount(saveCount);
171     }
172 
173     // Consume the touch events for the specified view.
addTouchView(View v)174     public void addTouchView(View v) {
175         v.setOnTouchListener(this);
176     }
177 
178     // This implements View.OnTouchListener so we intercept the touch events
179     // and pass them to ourselves.
onTouch(View v, MotionEvent event)180     public boolean onTouch(View v, MotionEvent event) {
181         onTouchEvent(event);
182         return true;
183     }
184 }
185