• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.camera.ui;
18 
19 import com.android.camera.R;
20 
21 import android.content.Context;
22 import android.os.Handler;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.widget.ImageView;
26 import android.widget.RelativeLayout;
27 
28 /**
29  * A view that contains camera zoom control which could adjust the zoom in/out
30  * if the camera supports zooming.
31  */
32 public abstract class ZoomControl extends RelativeLayout {
33     // The states of zoom button.
34     public static final int ZOOM_IN = 0;
35     public static final int ZOOM_OUT = 1;
36     public static final int ZOOM_STOP = 2;
37 
38     private static final String TAG = "ZoomControl";
39     private static final int ZOOMING_INTERVAL = 1000; // milliseconds
40 
41     protected ImageView mZoomIn;
42     protected ImageView mZoomOut;
43     protected ImageView mZoomSlider;
44     protected int mSliderPosition = 0;
45     protected int mDegree;
46     private Handler mHandler;
47 
48     public interface OnZoomChangedListener {
onZoomValueChanged(int index)49         void onZoomValueChanged(int index);  // only for immediate zoom
onZoomStateChanged(int state)50         void onZoomStateChanged(int state);  // only for smooth zoom
51     }
52 
53     // The interface OnZoomIndexChangedListener is used to inform the
54     // ZoomIndexBar about the zoom index change. The index position is between
55     // 0 (the index is zero) and 1.0 (the index is mZoomMax).
56     public interface OnZoomIndexChangedListener {
onZoomIndexChanged(double indexPosition)57         void onZoomIndexChanged(double indexPosition);
58     }
59 
60     protected int mZoomMax, mZoomIndex;
61     private boolean mSmoothZoomSupported;
62     private OnZoomChangedListener mListener;
63     private OnZoomIndexChangedListener mIndexListener;
64 
65     protected OnIndicatorEventListener mOnIndicatorEventListener;
66     private int mState;
67     private int mStep;
68 
69     protected final Runnable mRunnable = new Runnable() {
70         public void run() {
71             performZoom(mState, false);
72         }
73     };
74 
ZoomControl(Context context, AttributeSet attrs)75     public ZoomControl(Context context, AttributeSet attrs) {
76         super(context, attrs);
77         mZoomIn = addImageView(context, R.drawable.ic_zoom_in);
78         mZoomSlider = addImageView(context, R.drawable.ic_zoom_slider);
79         mZoomOut = addImageView(context, R.drawable.ic_zoom_out);
80         mHandler = new Handler();
81     }
82 
startZoomControl()83     public void startZoomControl() {
84         mZoomSlider.setPressed(true);
85         setZoomIndex(mZoomIndex); // Update the zoom index bar.
86     }
87 
addImageView(Context context, int iconResourceId)88     protected ImageView addImageView(Context context, int iconResourceId) {
89         ImageView image = new RotateImageView(context);
90         image.setImageResource(iconResourceId);
91         if (iconResourceId == R.drawable.ic_zoom_slider) {
92             image.setContentDescription(getResources().getString(
93                     R.string.accessibility_zoom_control));
94         } else {
95             image.setContentDescription(getResources().getString(
96                     R.string.empty));
97         }
98         addView(image);
99         return image;
100     }
101 
closeZoomControl()102     public void closeZoomControl() {
103         mZoomSlider.setPressed(false);
104         stopZooming();
105         if (!mSmoothZoomSupported) mHandler.removeCallbacks(mRunnable);
106         if (mOnIndicatorEventListener != null) {
107             mOnIndicatorEventListener.onIndicatorEvent(
108                     OnIndicatorEventListener.EVENT_LEAVE_ZOOM_CONTROL);
109         }
110     }
111 
setZoomMax(int zoomMax)112     public void setZoomMax(int zoomMax) {
113         mZoomMax = zoomMax;
114 
115         // Layout should be requested as the maximum zoom level is the key to
116         // show the correct zoom slider position.
117         requestLayout();
118     }
119 
setOnZoomChangeListener(OnZoomChangedListener listener)120     public void setOnZoomChangeListener(OnZoomChangedListener listener) {
121         mListener = listener;
122     }
123 
setOnIndicatorEventListener(OnIndicatorEventListener listener)124     public void setOnIndicatorEventListener(OnIndicatorEventListener listener) {
125         mOnIndicatorEventListener = listener;
126     }
127 
setZoomIndex(int index)128     public void setZoomIndex(int index) {
129         if (index < 0 || index > mZoomMax) {
130             throw new IllegalArgumentException("Invalid zoom value:" + index);
131         }
132         mZoomIndex = index;
133         invalidate();
134     }
135 
setSmoothZoomSupported(boolean smoothZoomSupported)136     public void setSmoothZoomSupported(boolean smoothZoomSupported) {
137         mSmoothZoomSupported = smoothZoomSupported;
138     }
139 
zoomIn()140     private boolean zoomIn() {
141         return (mZoomIndex == mZoomMax) ? false : changeZoomIndex(mZoomIndex + mStep);
142     }
143 
zoomOut()144     private boolean zoomOut() {
145         return (mZoomIndex == 0) ? false : changeZoomIndex(mZoomIndex - mStep);
146     }
147 
setZoomStep(int step)148     protected void setZoomStep(int step) {
149         mStep = step;
150     }
151 
stopZooming()152     private void stopZooming() {
153         if (mSmoothZoomSupported) {
154             if (mListener != null) mListener.onZoomStateChanged(ZOOM_STOP);
155         }
156     }
157 
158     // Called from ZoomControlWheel to change the zoom level.
159     // TODO: merge the zoom control for both platforms.
performZoom(int state)160     protected void performZoom(int state) {
161         performZoom(state, true);
162     }
163 
performZoom(int state, boolean fromUser)164     private void performZoom(int state, boolean fromUser) {
165         if ((mState == state) && fromUser) return;
166         if (fromUser) mHandler.removeCallbacks(mRunnable);
167         mState = state;
168         switch (state) {
169             case ZOOM_IN:
170                 zoomIn();
171                 break;
172             case ZOOM_OUT:
173                 zoomOut();
174                 break;
175             case ZOOM_STOP:
176                 stopZooming();
177                 break;
178         }
179         if (!mSmoothZoomSupported) {
180             // Repeat the zoom action on tablet as the user is still holding
181             // the zoom slider.
182             mHandler.postDelayed(mRunnable, ZOOMING_INTERVAL / mZoomMax);
183         }
184     }
185 
186     // Called from ZoomControlBar to change the zoom level.
performZoom(double zoomPercentage)187     protected void performZoom(double zoomPercentage) {
188         int index = (int) (mZoomMax * zoomPercentage);
189         if (mZoomIndex == index) return;
190         changeZoomIndex(index);
191    }
192 
changeZoomIndex(int index)193     private boolean changeZoomIndex(int index) {
194         if (mListener != null) {
195             if (mSmoothZoomSupported) {
196                 int zoomType = (index < mZoomIndex) ? ZOOM_OUT : ZOOM_IN;
197                 if (((zoomType == ZOOM_IN) && (mZoomIndex != mZoomMax)) ||
198                         ((zoomType == ZOOM_OUT) && (mZoomIndex != 0))) {
199                     mListener.onZoomStateChanged(zoomType);
200                 }
201             } else {
202                 if (index > mZoomMax) index = mZoomMax;
203                 if (index < 0) index = 0;
204                 mListener.onZoomValueChanged(index);
205                 mZoomIndex = index;
206             }
207         }
208         return true;
209     }
210 
setDegree(int degree)211     public void setDegree(int degree) {
212         mDegree = degree;
213         int count = getChildCount();
214         for (int i = 0 ; i < count ; ++i) {
215             View view = getChildAt(i);
216             if (view instanceof RotateImageView) {
217                 ((RotateImageView) view).setDegree(degree);
218             }
219         }
220     }
221 
222     @Override
setActivated(boolean activated)223     public void setActivated(boolean activated) {
224         super.setActivated(activated);
225         mZoomIn.setActivated(activated);
226         mZoomOut.setActivated(activated);
227     }
228 }
229