diff options
Diffstat (limited to 'src/com/android/camera/ui')
-rw-r--r-- | src/com/android/camera/ui/CameraPicker.java | 33 | ||||
-rw-r--r-- | src/com/android/camera/ui/IndicatorBar.java | 82 | ||||
-rw-r--r-- | src/com/android/camera/ui/IndicatorControl.java | 31 | ||||
-rw-r--r-- | src/com/android/camera/ui/IndicatorControlContainer.java | 135 | ||||
-rw-r--r-- | src/com/android/camera/ui/OnIndicatorEventListener.java | 25 | ||||
-rw-r--r-- | src/com/android/camera/ui/SecondLevelIndicatorBar.java | 118 | ||||
-rw-r--r-- | src/com/android/camera/ui/ZoomControl.java | 130 | ||||
-rw-r--r-- | src/com/android/camera/ui/ZoomControlBar.java | 158 | ||||
-rw-r--r-- | src/com/android/camera/ui/ZoomPicker.java | 143 |
9 files changed, 689 insertions, 166 deletions
diff --git a/src/com/android/camera/ui/CameraPicker.java b/src/com/android/camera/ui/CameraPicker.java index b77cb5f..43a1f16 100644 --- a/src/com/android/camera/ui/CameraPicker.java +++ b/src/com/android/camera/ui/CameraPicker.java @@ -16,7 +16,9 @@ package com.android.camera.ui; +import com.android.camera.CameraPreference.OnPreferenceChangedListener; import com.android.camera.ListPreference; +import com.android.camera.R; import android.content.Context; import android.hardware.Camera.CameraInfo; @@ -28,20 +30,20 @@ import android.widget.ImageView; * A view for switching the front/back camera. */ public class CameraPicker extends RotateImageView implements View.OnClickListener { - private Listener mListener; + private OnPreferenceChangedListener mListener; private ListPreference mPreference; private CharSequence[] mCameras; - private int mCameraIndex; + private int mCameraFacing; - public CameraPicker(Context context, AttributeSet attrs) { - super(context, attrs); + public CameraPicker(Context context) { + super(context); } - static public interface Listener { - public void onSharedPreferenceChanged(); + public CameraPicker(Context context, AttributeSet attrs) { + super(context, attrs); } - public void setListener(Listener listener) { + public void setListener(OnPreferenceChangedListener listener) { mListener = listener; } @@ -53,20 +55,27 @@ public class CameraPicker extends RotateImageView implements View.OnClickListene String cameraId = pref.getValue(); setVisibility(View.VISIBLE); if (mCameras[CameraInfo.CAMERA_FACING_FRONT].equals(cameraId)) { - mCameraIndex = CameraInfo.CAMERA_FACING_FRONT; + mCameraFacing = CameraInfo.CAMERA_FACING_FRONT; } else { - mCameraIndex = CameraInfo.CAMERA_FACING_BACK; + mCameraFacing = CameraInfo.CAMERA_FACING_BACK; } } + public void setCameraPickerIcon() { + setImageResource((mCameraFacing == CameraInfo.CAMERA_FACING_BACK) + ? R.drawable.ic_rotate_camera_facing_back + : R.drawable.ic_rotate_camera_facing_forward); + } + @Override public void onClick(View v) { if (mCameras == null) return; - int newCameraIndex = (mCameraIndex == CameraInfo.CAMERA_FACING_BACK) + int newCameraIndex = (mCameraFacing == CameraInfo.CAMERA_FACING_BACK) ? CameraInfo.CAMERA_FACING_FRONT : CameraInfo.CAMERA_FACING_BACK; - mCameraIndex = newCameraIndex; - mPreference.setValue((String) mCameras[mCameraIndex]); + mCameraFacing = newCameraIndex; + setCameraPickerIcon(); + mPreference.setValue((String) mCameras[mCameraFacing]); mListener.onSharedPreferenceChanged(); } } diff --git a/src/com/android/camera/ui/IndicatorBar.java b/src/com/android/camera/ui/IndicatorBar.java index 1e52f9c..e470b4e 100644 --- a/src/com/android/camera/ui/IndicatorBar.java +++ b/src/com/android/camera/ui/IndicatorBar.java @@ -16,19 +16,27 @@ package com.android.camera.ui; +import com.android.camera.CameraPreference.OnPreferenceChangedListener; +import com.android.camera.CameraSettings; +import com.android.camera.PreferenceGroup; +import com.android.camera.R; +import com.android.camera.Util; + import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; - -import java.util.ArrayList; +import android.view.View; +import android.widget.ImageView; /** - * A view that contains camera setting indicators which are spread over a - * vertical bar in preview frame. + * A view that contains the top-level indicator control. */ -public class IndicatorBar extends IndicatorControl { +public class IndicatorBar extends IndicatorControl implements + View.OnClickListener { private static final String TAG = "IndicatorBar"; - int mSelectedIndex = -1; + + private ImageView mZoomIcon; + private ImageView mSecondLevelIcon; public IndicatorBar(Context context) { super(context); @@ -38,48 +46,50 @@ public class IndicatorBar extends IndicatorControl { super(context, attrs); } - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (!onFilterTouchEventForSecurity(event)) return false; - - int action = event.getAction(); - - if (!isEnabled()) return false; + public void initialize(Context context, PreferenceGroup group, + String flashSetting, boolean zoomSupported) { + // From UI spec, we have camera_flash setting on the first level. + super.initialize(context, group, new String[] {flashSetting}, null); - double x = (double) event.getX(); - double y = (double) event.getY(); - if (x > getWidth() || x < 0) return false; - if (y > getHeight() || y < 0) return false; + // add Zoom Icon. + if (zoomSupported) { + mZoomIcon = (ImageView) findViewById(R.id.zoom_control_icon); + mZoomIcon.setOnClickListener(this); + mZoomIcon.setVisibility(View.VISIBLE); + } - int index = (int) (y * getChildCount()) / getHeight(); - AbstractIndicatorButton b = (AbstractIndicatorButton) getChildAt(index); - b.dispatchTouchEvent(event); - if ((mSelectedIndex != -1) && (index != mSelectedIndex)) { - AbstractIndicatorButton c = (AbstractIndicatorButton) getChildAt(mSelectedIndex); - event.setAction(MotionEvent.ACTION_CANCEL); - c.dispatchTouchEvent(event); - c.dismissPopup(); + mSecondLevelIcon = (ImageView) findViewById(R.id.second_level_indicator_bar_icon); + mSecondLevelIcon.setOnClickListener(this); + requestLayout(); + } - if (action == MotionEvent.ACTION_MOVE) { - event.setAction(MotionEvent.ACTION_DOWN); - b.dispatchTouchEvent(event); - } + public void onClick(View view) { + dismissSettingPopup(); + if (view == mZoomIcon) { + mOnIndicatorEventListener.onIndicatorEvent( + OnIndicatorEventListener.EVENT_ENTER_ZOOM_CONTROL_BAR); + } else if (view == mSecondLevelIcon) { + mOnIndicatorEventListener.onIndicatorEvent( + OnIndicatorEventListener.EVENT_ENTER_SECOND_LEVEL_INDICATOR_BAR); } - mSelectedIndex = index; - return true; } @Override protected void onLayout( boolean changed, int left, int top, int right, int bottom) { + // Layout the static components. + super.onLayout(changed, left, top, right, bottom); + int count = getChildCount(); if (count == 0) return; int width = right - left; - int height = bottom - top; - int h = height / count; - for (int i = 0; i < count; i++) { - getChildAt(i).layout(0, top + i * height / count, width, - top + i * height / count + h); + View view; + for (int i = 0 ; i < count ; i++) { + view = getChildAt(i); + if (view instanceof IndicatorButton) { + view.layout(0, 0, width, width); + return; + } } } } diff --git a/src/com/android/camera/ui/IndicatorControl.java b/src/com/android/camera/ui/IndicatorControl.java index d90768f..57ec318 100644 --- a/src/com/android/camera/ui/IndicatorControl.java +++ b/src/com/android/camera/ui/IndicatorControl.java @@ -16,15 +16,18 @@ package com.android.camera.ui; +import com.android.camera.CameraPreference.OnPreferenceChangedListener; import com.android.camera.IconListPreference; +import com.android.camera.ListPreference; import com.android.camera.PreferenceGroup; +import com.android.camera.CameraSettings; import com.android.camera.R; import android.content.Context; import android.util.AttributeSet; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.RelativeLayout; import java.util.ArrayList; @@ -32,25 +35,21 @@ import java.util.ArrayList; * A view that contains camera setting indicators. The indicators are spreaded * differently based on the screen resolution. */ -public abstract class IndicatorControl extends ViewGroup implements +public abstract class IndicatorControl extends RelativeLayout implements IndicatorButton.Listener, OtherSettingsPopup.Listener { private static final String TAG = "IndicatorControl"; private Context mContext; - private Listener mListener; + private OnPreferenceChangedListener mListener; + protected OnIndicatorEventListener mOnIndicatorEventListener; private PreferenceGroup mPreferenceGroup; + private int mDegree = 0; ArrayList<AbstractIndicatorButton> mIndicators = new ArrayList<AbstractIndicatorButton>(); - static public interface Listener { - public void onSharedPreferenceChanged(); - public void onRestorePreferencesClicked(); - public void onOverriddenPreferencesClicked(); - } - - public void setListener(Listener listener) { + public void setListener(OnPreferenceChangedListener listener) { mListener = listener; } @@ -65,6 +64,7 @@ public abstract class IndicatorControl extends ViewGroup implements } public void setDegree(int degree) { + mDegree = degree; int count = getChildCount(); for (int i = 0 ; i < count ; ++i) { View view = getChildAt(i); @@ -74,6 +74,16 @@ public abstract class IndicatorControl extends ViewGroup implements } } + public void setOnIndicatorEventListener(OnIndicatorEventListener listener) { + mOnIndicatorEventListener = listener; + } + + // For the initialization of first-level indicator bar. + public void initialize(Context context, PreferenceGroup group, + String flashSetting, String[] keys, String[] otherSettingKeys) { + initialize(context, group, keys, otherSettingKeys); + } + public void initialize(Context context, PreferenceGroup group, String[] keys, String[] otherSettingKeys) { // Reset the variables and states. @@ -93,7 +103,6 @@ public abstract class IndicatorControl extends ViewGroup implements addIndicator(context, pref); } } - requestLayout(); } diff --git a/src/com/android/camera/ui/IndicatorControlContainer.java b/src/com/android/camera/ui/IndicatorControlContainer.java new file mode 100644 index 0000000..d5c07c5 --- /dev/null +++ b/src/com/android/camera/ui/IndicatorControlContainer.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.CameraPreference.OnPreferenceChangedListener; +import com.android.camera.PreferenceGroup; +import com.android.camera.R; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; + +/** + * A view contains indicator control bar, second-level indicator bar and + * zoom control. + */ +public class IndicatorControlContainer extends IndicatorControl implements + OnIndicatorEventListener { + private static final String TAG = "IndicatorControlContainer"; + + private Animation mFadeIn, mFadeOut; + private IndicatorBar mIndicatorBar; + private ZoomControlBar mZoomControlBar; + private SecondLevelIndicatorBar mSecondLevelIndicatorBar; + + public IndicatorControlContainer(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void initialize(Context context, PreferenceGroup group, + String flashSetting, String[] secondLevelKeys, + String[] secondLevelOtherSettingKeys) { + mIndicatorBar = (IndicatorBar) + findViewById(R.id.indicator_bar); + + mZoomControlBar = (ZoomControlBar) + findViewById(R.id.zoom_control); + mZoomControlBar.setOnIndicatorEventListener(this); + + // We need to show/hide the zoom slider icon accordingly. + // From UI spec, we have camera_flash setting on the first level. + mIndicatorBar.initialize(context, group, flashSetting, + mZoomControlBar.isZoomSupported()); + mIndicatorBar.setOnIndicatorEventListener(this); + + mSecondLevelIndicatorBar = (SecondLevelIndicatorBar) + findViewById(R.id.second_level_indicator_bar); + mSecondLevelIndicatorBar.initialize(context, group, secondLevelKeys, + secondLevelOtherSettingKeys); + mSecondLevelIndicatorBar.setOnIndicatorEventListener(this); + + mFadeIn = AnimationUtils.loadAnimation( + context, R.anim.grow_fade_in_from_bottom); + mFadeOut = AnimationUtils.loadAnimation( + context, R.anim.shrink_fade_out_from_top); + } + + public void setDegree(int degree) { + mIndicatorBar.setDegree(degree); + mSecondLevelIndicatorBar.setDegree(degree); + mZoomControlBar.setDegree(degree); + } + + public void onIndicatorEvent(int event) { + switch (event) { + case OnIndicatorEventListener.EVENT_ENTER_SECOND_LEVEL_INDICATOR_BAR: + mIndicatorBar.setVisibility(View.GONE); + mSecondLevelIndicatorBar.startAnimation(mFadeIn); + mSecondLevelIndicatorBar.setVisibility(View.VISIBLE); + break; + + case OnIndicatorEventListener.EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR: + mSecondLevelIndicatorBar.startAnimation(mFadeOut); + mSecondLevelIndicatorBar.setVisibility(View.GONE); + mIndicatorBar.setVisibility(View.VISIBLE); + break; + + case OnIndicatorEventListener.EVENT_ENTER_ZOOM_CONTROL_BAR: + mIndicatorBar.setVisibility(View.GONE); + mZoomControlBar.setVisibility(View.VISIBLE); + break; + + case OnIndicatorEventListener.EVENT_LEAVE_ZOOM_CONTROL_BAR: + mZoomControlBar.setVisibility(View.GONE); + mIndicatorBar.setVisibility(View.VISIBLE); + break; + } + } + + public void reloadPreferences() { + mIndicatorBar.reloadPreferences(); + mSecondLevelIndicatorBar.reloadPreferences(); + } + + public void setListener(OnPreferenceChangedListener listener) { + mIndicatorBar.setListener(listener); + mSecondLevelIndicatorBar.setListener(listener); + } + + @Override + public View getActiveSettingPopup() { + if (mIndicatorBar.getVisibility() == View.VISIBLE) { + return mIndicatorBar.getActiveSettingPopup(); + } else if (mSecondLevelIndicatorBar.getVisibility() == View.VISIBLE) { + return mSecondLevelIndicatorBar.getActiveSettingPopup(); + } + return null; + } + + public boolean dismissSettingPopup() { + if (mIndicatorBar.getVisibility() == View.VISIBLE) { + return mIndicatorBar.dismissSettingPopup(); + } else if (mSecondLevelIndicatorBar.getVisibility() == View.VISIBLE) { + return mSecondLevelIndicatorBar.dismissSettingPopup(); + } + return false; + } +} diff --git a/src/com/android/camera/ui/OnIndicatorEventListener.java b/src/com/android/camera/ui/OnIndicatorEventListener.java new file mode 100644 index 0000000..f4e1deb --- /dev/null +++ b/src/com/android/camera/ui/OnIndicatorEventListener.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +public interface OnIndicatorEventListener { + public static int EVENT_ENTER_SECOND_LEVEL_INDICATOR_BAR = 0; + public static int EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR = 1; + public static int EVENT_ENTER_ZOOM_CONTROL_BAR = 2; + public static int EVENT_LEAVE_ZOOM_CONTROL_BAR = 3; + void onIndicatorEvent(int event); +} diff --git a/src/com/android/camera/ui/SecondLevelIndicatorBar.java b/src/com/android/camera/ui/SecondLevelIndicatorBar.java new file mode 100644 index 0000000..9a697fe --- /dev/null +++ b/src/com/android/camera/ui/SecondLevelIndicatorBar.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.PreferenceGroup; +import com.android.camera.R; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; + +/** + * A view that contains camera setting indicators which are spread over a + * vertical bar in preview frame. + */ +public class SecondLevelIndicatorBar extends IndicatorControl implements + View.OnClickListener { + private static final String TAG = "SecondLevelIndicatorBar"; + private ImageView mCloseIcon; + int mDegree = 0; + int mSelectedIndex = -1; + + public SecondLevelIndicatorBar(Context context) { + super(context); + } + + public SecondLevelIndicatorBar(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void initialize(Context context, PreferenceGroup group, + String[] keys, String[] otherSettingKeys) { + if (mCloseIcon == null) { + mCloseIcon = new ImageView(context); + mCloseIcon.setImageResource(R.drawable.btn_close_settings); + mCloseIcon.setOnClickListener(this); + addView(mCloseIcon); + } + super.initialize(context, group, keys, otherSettingKeys); + if (mDegree != 0) setDegree(mDegree); + } + + public void onClick(View view) { + dismissSettingPopup(); + mOnIndicatorEventListener.onIndicatorEvent( + OnIndicatorEventListener.EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (!onFilterTouchEventForSecurity(event)) return false; + + int action = event.getAction(); + if (!isEnabled()) return false; + + double x = (double) event.getX(); + double y = (double) event.getY(); + if (x > getWidth()) x = getWidth(); + if (y > getHeight()) y = getHeight(); + + int index = (int) (y * getChildCount()) / getHeight(); + View b = getChildAt(index); + b.dispatchTouchEvent(event); + if ((mSelectedIndex != -1) && (index != mSelectedIndex)) { + View v = getChildAt(mSelectedIndex); + if (v instanceof AbstractIndicatorButton) { + AbstractIndicatorButton c = (AbstractIndicatorButton) v; + event.setAction(MotionEvent.ACTION_CANCEL); + c.dispatchTouchEvent(event); + c.dismissPopup(); + } + + if (action == MotionEvent.ACTION_MOVE) { + event.setAction(MotionEvent.ACTION_DOWN); + b.dispatchTouchEvent(event); + } + } + mSelectedIndex = index; + return true; + } + + @Override + public void setDegree(int degree) { + mDegree = degree; + super.setDegree(degree); + } + + @Override + protected void onLayout( + boolean changed, int left, int top, int right, int bottom) { + int count = getChildCount(); + if (count == 0) return; + int width = right - left; + int height = bottom - top; + int h = height / count; + for (int i = 0; i < count; i++) { + getChildAt(i).layout(0, top + i * height / count, width, + top + i * height / count + h); + } + } +} diff --git a/src/com/android/camera/ui/ZoomControl.java b/src/com/android/camera/ui/ZoomControl.java new file mode 100644 index 0000000..142e4b8 --- /dev/null +++ b/src/com/android/camera/ui/ZoomControl.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.R; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.RelativeLayout; + +/** + * A view that contains camera zoom control which could adjust the zoom in/out + * if the camera supports zooming. + */ +public abstract class ZoomControl extends RelativeLayout { + private static final String TAG = "ZoomControl"; + + public interface OnZoomChangedListener { + void onZoomValueChanged(int index); // only for immediate zoom + void onZoomStateChanged(int state); // only for smooth zoom + } + + private int mZoomMax, mZoomIndex; + private boolean mSmoothZoomSupported; + private OnZoomChangedListener mListener; + private boolean mZoomSupported = true; + + // The state of zoom button. + public static final int ZOOM_IN = 0; + public static final int ZOOM_OUT = 1; + public static final int ZOOM_STOP = 2; + + protected OnIndicatorEventListener mOnIndicatorEventListener; + + public ZoomControl(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public abstract void initialize(Context context); + + public void setZoomMax(int zoomMax) { + mZoomMax = zoomMax; + } + + public void setZoomSupported(boolean supported) { + mZoomSupported = supported; + } + + public boolean isZoomSupported() { + return mZoomSupported; + } + + public void setOnZoomChangeListener(OnZoomChangedListener listener) { + mListener = listener; + } + + public void setOnIndicatorEventListener(OnIndicatorEventListener listener) { + mOnIndicatorEventListener = listener; + } + + public void setZoomIndex(int index) { + if (index < 0 || index > mZoomMax) { + throw new IllegalArgumentException("Invalid zoom value:" + index); + } + mZoomIndex = index; + } + + public void setSmoothZoomSupported(boolean smoothZoomSupported) { + mSmoothZoomSupported = smoothZoomSupported; + } + + public boolean zoomIn() { + return (mZoomIndex == mZoomMax) ? false : changeZoomIndex(mZoomIndex + 1); + } + + public boolean zoomOut() { + return (mZoomIndex == 0) ? false : changeZoomIndex(mZoomIndex - 1); + } + + public void stopZooming() { + if (mSmoothZoomSupported) { + if (mListener != null) mListener.onZoomStateChanged(ZOOM_STOP); + } + } + + private boolean changeZoomIndex(int index) { + int zoomType = (index < mZoomIndex) ? ZOOM_OUT : ZOOM_IN; + if (mListener != null) { + if (mSmoothZoomSupported) { + if (((zoomType == ZOOM_IN) && (mZoomIndex != mZoomMax)) || + ((zoomType == ZOOM_OUT) && (mZoomIndex != 0))) { + mListener.onZoomStateChanged(zoomType); + } + } else { + mListener.onZoomStateChanged(index); + } + mZoomIndex = index; + } + return true; + } + + public void setDegree(int degree) { + int count = getChildCount(); + for (int i = 0 ; i < count ; ++i) { + View view = getChildAt(i); + if (view instanceof RotateImageView) { + ((RotateImageView) view).setDegree(degree); + } + } + } + + protected int getZoomIndex() { + return mZoomIndex; + } +} diff --git a/src/com/android/camera/ui/ZoomControlBar.java b/src/com/android/camera/ui/ZoomControlBar.java new file mode 100644 index 0000000..07ad143 --- /dev/null +++ b/src/com/android/camera/ui/ZoomControlBar.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.R; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; + +/** + * A view that contains camera zoom control and its layout. + */ +public class ZoomControlBar extends ZoomControl { + private static final String TAG = "ZoomControlBar"; + + private static final int ZOOMING_INTERVAL = 300; // milliseconds + + private ImageView mZoomIn; + private ImageView mZoomOut; + private ImageView mZoomSlider; + private View mBar; + private int mSliderPosition = 0; + private Handler mHandler; + private int mDegree; + + private final Runnable mRunnable = new Runnable() { + public void run() { + if (mSliderPosition < 0) { + zoomIn(); + } else if (mSliderPosition > 0) { + zoomOut(); + } + if (mSliderPosition != 0) mHandler.postDelayed(mRunnable, ZOOMING_INTERVAL); + } + }; + + public ZoomControlBar(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void initialize(Context context) { + mZoomIn = addImageView(context, R.drawable.ic_zoom_in_holo_light); + mBar = new View(context); + mBar.setBackgroundResource(R.drawable.ic_zoom_big); + addView(mBar); + mZoomSlider = addImageView(context, R.drawable.btn_zoom_slider); + mZoomOut = addImageView(context, R.drawable.ic_zoom_out_holo_light); + mHandler = new Handler(); + } + + ImageView addImageView(Context context, int iconResourceId) { + ImageView image = new RotateImageView(context); + image.setImageResource(iconResourceId); + addView(image); + return image; + } + + private void closeControl() { + mHandler.removeCallbacks(mRunnable); + mSliderPosition = 0; + stopZooming(); + mOnIndicatorEventListener.onIndicatorEvent( + OnIndicatorEventListener.EVENT_LEAVE_ZOOM_CONTROL_BAR); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (!onFilterTouchEventForSecurity(event)) return false; + + int action = event.getAction(); + + if (!isEnabled()) return false; + + double y = (double) event.getY(); + int offset = getHeight() / 2; + + // For left-hand users, as the device is rotated for 180 degree for + // landscape mode, the zoom-in bottom should be on the top, so the + // position should be reversed. + if (mDegree == 180) { + mSliderPosition = offset - (int) y; + } else { + mSliderPosition = (int) y - offset; + } + // TODO: add fast zoom change here + + switch (action) { + case MotionEvent.ACTION_DOWN: + mHandler.postDelayed(mRunnable, ZOOMING_INTERVAL); + mZoomSlider.setPressed(true); + break; + case MotionEvent.ACTION_OUTSIDE: + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mZoomSlider.setPressed(false); + closeControl(); + break; + default: + requestLayout(); + } + return true; + } + + @Override + public void setDegree(int degree) { + // layout for the left-hand camera control + if ((degree == 180) || (mDegree == 180)) requestLayout(); + mDegree = degree; + super.setDegree(degree); + } + + @Override + protected void onLayout( + boolean changed, int left, int top, int right, int bottom) { + int width = right - left; + int height = bottom - top; + int h = height / 2; + int pos; + + // For left-hand users, as the device is rotated for 180 degree, + // the zoom-in button should be on the top. + if (mDegree == 180) { + pos = h - mSliderPosition - width / 2; + mZoomOut.layout(0, top, width, top + width); + mZoomIn.layout(0, bottom - width, width, bottom); + } else { + pos = h + mSliderPosition - width / 2; + mZoomIn.layout(0, top, width, top + width); + mZoomOut.layout(0, bottom - width, width, bottom); + } + mBar.layout(0, top + width, width, bottom - width); + if (pos < width) { + pos = width; + } else if (pos > (height - 2 * width)) { + pos = height - 2 * width; + } + mZoomSlider.layout(0, pos, width, pos + width); + } +} diff --git a/src/com/android/camera/ui/ZoomPicker.java b/src/com/android/camera/ui/ZoomPicker.java index 3979bca..75db254 100644 --- a/src/com/android/camera/ui/ZoomPicker.java +++ b/src/com/android/camera/ui/ZoomPicker.java @@ -16,152 +16,81 @@ package com.android.camera.ui; +import com.android.camera.R; + import android.content.Context; import android.os.Handler; +import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; -import java.util.Formatter; - /** * A class to increase or decrease zoom */ -public class ZoomPicker { +public class ZoomPicker extends ZoomControl { private final String TAG = "ZoomPicker"; - private int mZoomMax, mZoomIndex; - private boolean mSmoothZoomSupported; - private OnZoomChangedListener mListener; - private boolean mIncrement, mDecrement; - private final StringBuilder mBuilder = new StringBuilder(); - private final Formatter mFormatter = new Formatter(mBuilder); - private final Object[] mFormatterArgs = new Object[1]; + private View mIncrementButton; private View mDecrementButton; - - // The state of zoom button. - public static final int ZOOM_IN = 0; - public static final int ZOOM_OUT = 1; - public static final int ZOOM_STOP = 2; + private int mState = ZOOM_STOP; private Handler mHandler; + + public ZoomPicker(Context context, AttributeSet attrs) { + super(context, attrs); + } + private final Runnable mRunnable = new Runnable() { public void run() { - if (mIncrement) { - if (mSmoothZoomSupported) { - if (mZoomIndex != mZoomMax && mListener != null) { - mListener.onZoomStateChanged(ZOOM_IN); - } - } else if (changeZoomIndex(mZoomIndex + 1)) { - mHandler.postDelayed(this, 65); - } - } else if (mDecrement) { - if (mSmoothZoomSupported) { - if (mZoomIndex != 0 && mListener != null) { - mListener.onZoomStateChanged(ZOOM_OUT); - } - } else if (changeZoomIndex(mZoomIndex - 1)) { - mHandler.postDelayed(this, 65); - } - } + if (zooming()) mHandler.postDelayed(this, 65); } }; - public ZoomPicker(Context context, View increment, View decrement) { - mHandler = new Handler(); - - OnTouchListener incrementTouchListener = new OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - int action = event.getAction(); - if (action == MotionEvent.ACTION_DOWN) { - if (!mIncrement && changeZoomIndex(mZoomIndex + 1)) { - mIncrement = true; - // Give bigger delay so users can tap to change only one - // zoom step. - mHandler.postDelayed(mRunnable, 300); - } - } else if (action == MotionEvent.ACTION_UP - || action == MotionEvent.ACTION_CANCEL) { - mIncrement = false; - if (mSmoothZoomSupported) { - if (mListener != null) mListener.onZoomStateChanged(ZOOM_STOP); - } - } + private boolean zooming() { + switch (mState) { + case ZOOM_IN: + return zoomIn(); + case ZOOM_OUT: + return zoomOut(); + default: return false; - } - }; + } + } + + @Override + public void initialize(Context context) { + final View increment = getRootView().findViewById(R.id.zoom_increment); + final View decrement = getRootView().findViewById(R.id.zoom_decrement); + + mHandler = new Handler(); - OnTouchListener decrementTouchListener = new OnTouchListener() { + OnTouchListener touchListener = new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { - if (!mDecrement && changeZoomIndex(mZoomIndex - 1)) { - mDecrement = true; - // Give bigger delay so users can tap to change only one - // zoom step. - mHandler.postDelayed(mRunnable, 300); - } + mState = (v == increment) ? ZOOM_IN : ZOOM_OUT; + if (zooming()) mHandler.postDelayed(mRunnable, 300); } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - mDecrement = false; - if (mSmoothZoomSupported) { - if (mListener != null) mListener.onZoomStateChanged(ZOOM_STOP); - } + mState = ZOOM_STOP; + stopZooming(); } return false; } }; mIncrementButton = increment; - mIncrementButton.setOnTouchListener(incrementTouchListener); + mIncrementButton.setOnTouchListener(touchListener); mIncrementButton.setVisibility(View.VISIBLE); mDecrementButton = decrement; - mDecrementButton.setOnTouchListener(decrementTouchListener); + mDecrementButton.setOnTouchListener(touchListener); mDecrementButton.setVisibility(View.VISIBLE); } - public void setOnZoomChangeListener(OnZoomChangedListener listener) { - mListener = listener; - } - - public interface OnZoomChangedListener { - void onZoomValueChanged(int index); // only for immediate zoom - void onZoomStateChanged(int state); // only for smooth zoom - } - - public void setZoomMax(int zoomMax) { - mZoomMax = zoomMax; - } - - public void setZoomIndex(int index) { - if (index < 0 || index > mZoomMax) { - throw new IllegalArgumentException("Invalid zoom value:" + index); - } - mZoomIndex = index; - } - - public void setSmoothZoomSupported(boolean smoothZoomSupported) { - mSmoothZoomSupported = smoothZoomSupported; - } - - private boolean changeZoomIndex(int index) { - if (index > mZoomMax || index < 0) return false; - mZoomIndex = index; - if (mListener != null) { - mListener.onZoomValueChanged(mZoomIndex); - } - return true; - } - - private String formatZoomRatio(float value) { - mFormatterArgs[0] = value; - mBuilder.delete(0, mBuilder.length()); - mFormatter.format("%2.1fx", mFormatterArgs); - return mFormatter.toString(); - } - public void setEnabled(boolean enabled) { mIncrementButton.setEnabled(enabled); mDecrementButton.setEnabled(enabled); } + } |