diff options
44 files changed, 901 insertions, 288 deletions
diff --git a/res/anim/grow_fade_in_from_bottom.xml b/res/anim/grow_fade_in_from_bottom.xml new file mode 100644 index 0000000..df5bdf4 --- /dev/null +++ b/res/anim/grow_fade_in_from_bottom.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> + <scale android:interpolator="@android:interpolator/decelerate_quint" + android:fromXScale="1.0" android:toXScale="1.0" + android:fromYScale="0.2" android:toYScale="1.0" + android:pivotX="100%" android:pivotY="100%" + android:duration="300" /> + <alpha android:interpolator="@android:interpolator/decelerate_cubic" + android:fromAlpha="0.5" android:toAlpha="1.0" + android:duration="300" /> +</set> diff --git a/res/anim/shrink_fade_out_from_top.xml b/res/anim/shrink_fade_out_from_top.xml new file mode 100644 index 0000000..4df151c --- /dev/null +++ b/res/anim/shrink_fade_out_from_top.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> + <scale android:interpolator="@android:interpolator/decelerate_quint" + android:fromXScale="1.0" android:toXScale="1.0" + android:fromYScale="1.0" android:toYScale="0.2" + android:pivotX="100%" android:pivotY="100%" + android:duration="300" /> + <alpha android:interpolator="@android:interpolator/decelerate_cubic" + android:fromAlpha="1.0" android:toAlpha="0.0" + android:duration="300" /> +</set> diff --git a/res/drawable-hdpi/btn_close_settings.png b/res/drawable-hdpi/btn_close_settings.png Binary files differnew file mode 100644 index 0000000..3774aea --- /dev/null +++ b/res/drawable-hdpi/btn_close_settings.png diff --git a/res/drawable-hdpi/btn_zoom_control.png b/res/drawable-hdpi/btn_zoom_control.png Binary files differnew file mode 100644 index 0000000..b9c1c98 --- /dev/null +++ b/res/drawable-hdpi/btn_zoom_control.png diff --git a/res/drawable-hdpi/ic_rotate_camera_facing_back.png b/res/drawable-hdpi/ic_rotate_camera_facing_back.png Binary files differnew file mode 100644 index 0000000..cca4636 --- /dev/null +++ b/res/drawable-hdpi/ic_rotate_camera_facing_back.png diff --git a/res/drawable-hdpi/ic_rotate_camera_facing_forward.png b/res/drawable-hdpi/ic_rotate_camera_facing_forward.png Binary files differnew file mode 100644 index 0000000..6def0c7 --- /dev/null +++ b/res/drawable-hdpi/ic_rotate_camera_facing_forward.png diff --git a/res/drawable-hdpi/ic_settings_holo_light.png b/res/drawable-hdpi/ic_settings_holo_light.png Binary files differnew file mode 100644 index 0000000..24d074c --- /dev/null +++ b/res/drawable-hdpi/ic_settings_holo_light.png diff --git a/res/drawable-hdpi/ic_zoom_big.9.png b/res/drawable-hdpi/ic_zoom_big.9.png Binary files differnew file mode 100644 index 0000000..22425ca --- /dev/null +++ b/res/drawable-hdpi/ic_zoom_big.9.png diff --git a/res/drawable-hdpi/ic_zoom_in_holo_light.png b/res/drawable-hdpi/ic_zoom_in_holo_light.png Binary files differnew file mode 100644 index 0000000..df1e925 --- /dev/null +++ b/res/drawable-hdpi/ic_zoom_in_holo_light.png diff --git a/res/drawable-hdpi/ic_zoom_out_holo_light.png b/res/drawable-hdpi/ic_zoom_out_holo_light.png Binary files differnew file mode 100644 index 0000000..5ce6c42 --- /dev/null +++ b/res/drawable-hdpi/ic_zoom_out_holo_light.png diff --git a/res/drawable-hdpi/ic_zoom_slider.png b/res/drawable-hdpi/ic_zoom_slider.png Binary files differnew file mode 100644 index 0000000..606fc30 --- /dev/null +++ b/res/drawable-hdpi/ic_zoom_slider.png diff --git a/res/drawable-hdpi/ic_zoom_slider_pressed.png b/res/drawable-hdpi/ic_zoom_slider_pressed.png Binary files differnew file mode 100644 index 0000000..af55061 --- /dev/null +++ b/res/drawable-hdpi/ic_zoom_slider_pressed.png diff --git a/res/drawable-mdpi/ic_rotate_camera_facing_back.png b/res/drawable-mdpi/ic_rotate_camera_facing_back.png Binary files differnew file mode 100644 index 0000000..0adc8bd --- /dev/null +++ b/res/drawable-mdpi/ic_rotate_camera_facing_back.png diff --git a/res/drawable-mdpi/ic_rotate_camera_facing_forward.png b/res/drawable-mdpi/ic_rotate_camera_facing_forward.png Binary files differnew file mode 100644 index 0000000..bb373af --- /dev/null +++ b/res/drawable-mdpi/ic_rotate_camera_facing_forward.png diff --git a/res/drawable-mdpi/ic_settings_holo_light.png b/res/drawable-mdpi/ic_settings_holo_light.png Binary files differnew file mode 100644 index 0000000..dba8990 --- /dev/null +++ b/res/drawable-mdpi/ic_settings_holo_light.png diff --git a/res/drawable-mdpi/ic_zoom_in_holo_light.png b/res/drawable-mdpi/ic_zoom_in_holo_light.png Binary files differnew file mode 100644 index 0000000..0d22534 --- /dev/null +++ b/res/drawable-mdpi/ic_zoom_in_holo_light.png diff --git a/res/drawable-mdpi/ic_zoom_out_holo_light.png b/res/drawable-mdpi/ic_zoom_out_holo_light.png Binary files differnew file mode 100644 index 0000000..9cb7c3d --- /dev/null +++ b/res/drawable-mdpi/ic_zoom_out_holo_light.png diff --git a/res/drawable-mdpi/ic_zoom_slider.png b/res/drawable-mdpi/ic_zoom_slider.png Binary files differnew file mode 100644 index 0000000..359dae2 --- /dev/null +++ b/res/drawable-mdpi/ic_zoom_slider.png diff --git a/res/drawable-mdpi/ic_zoom_slider_pressed.png b/res/drawable-mdpi/ic_zoom_slider_pressed.png Binary files differnew file mode 100644 index 0000000..14acd6a --- /dev/null +++ b/res/drawable-mdpi/ic_zoom_slider_pressed.png diff --git a/res/drawable-xhdpi/ic_rotate_camera_facing_back.png b/res/drawable-xhdpi/ic_rotate_camera_facing_back.png Binary files differnew file mode 100644 index 0000000..1caf7e7 --- /dev/null +++ b/res/drawable-xhdpi/ic_rotate_camera_facing_back.png diff --git a/res/drawable-xhdpi/ic_rotate_camera_facing_forward.png b/res/drawable-xhdpi/ic_rotate_camera_facing_forward.png Binary files differnew file mode 100644 index 0000000..46ce681 --- /dev/null +++ b/res/drawable-xhdpi/ic_rotate_camera_facing_forward.png diff --git a/res/drawable-xhdpi/ic_settings_holo_light.png b/res/drawable-xhdpi/ic_settings_holo_light.png Binary files differnew file mode 100644 index 0000000..3a5d0ba --- /dev/null +++ b/res/drawable-xhdpi/ic_settings_holo_light.png diff --git a/res/drawable-xhdpi/ic_zoom_in_holo_light.png b/res/drawable-xhdpi/ic_zoom_in_holo_light.png Binary files differnew file mode 100644 index 0000000..07ba15f --- /dev/null +++ b/res/drawable-xhdpi/ic_zoom_in_holo_light.png diff --git a/res/drawable-xhdpi/ic_zoom_out_holo_light.png b/res/drawable-xhdpi/ic_zoom_out_holo_light.png Binary files differnew file mode 100644 index 0000000..f6a5d3a --- /dev/null +++ b/res/drawable-xhdpi/ic_zoom_out_holo_light.png diff --git a/res/drawable-xhdpi/ic_zoom_slider.png b/res/drawable-xhdpi/ic_zoom_slider.png Binary files differnew file mode 100644 index 0000000..441220c --- /dev/null +++ b/res/drawable-xhdpi/ic_zoom_slider.png diff --git a/res/drawable-xhdpi/ic_zoom_slider_pressed.png b/res/drawable-xhdpi/ic_zoom_slider_pressed.png Binary files differnew file mode 100644 index 0000000..be1f7ee --- /dev/null +++ b/res/drawable-xhdpi/ic_zoom_slider_pressed.png diff --git a/res/drawable/btn_zoom_slider.xml b/res/drawable/btn_zoom_slider.xml new file mode 100644 index 0000000..6ecdf19 --- /dev/null +++ b/res/drawable/btn_zoom_slider.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" android:drawable="@drawable/ic_zoom_slider_pressed" /> + <item android:drawable="@drawable/ic_zoom_slider" /> +</selector> + diff --git a/res/layout-w1024dp/camera_control.xml b/res/layout-w1024dp/camera_control.xml index 342d167..9897dc6 100644 --- a/res/layout-w1024dp/camera_control.xml +++ b/res/layout-w1024dp/camera_control.xml @@ -40,6 +40,11 @@ android:clickable="true" android:focusable="true" android:background="@drawable/btn_shutter" /> + <com.android.camera.ui.ZoomPicker + android:id="@+id/zoom_control" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone"/> <com.android.camera.ui.RotateImageView android:id="@+id/zoom_increment" android:clickable="true" android:layout_width="wrap_content" diff --git a/res/layout/camera_control.xml b/res/layout/camera_control.xml index 6347f3c..ea9c3fe 100644 --- a/res/layout/camera_control.xml +++ b/res/layout/camera_control.xml @@ -24,13 +24,13 @@ <include layout="@layout/review_thumbnail"/> <com.android.camera.ui.CameraPicker android:id="@+id/camera_picker" - android:clickable="true" - android:layout_centerVertical="true" - android:layout_centerHorizontal="true" - android:layout_below="@+id/share_button" - android:layout_above="@+id/shutter_button" - android:layout_width="36dp" - android:layout_height="36dp" /> + android:clickable="true" + android:layout_centerVertical="true" + android:layout_centerHorizontal="true" + android:layout_below="@+id/share_button" + android:layout_above="@+id/shutter_button" + android:layout_width="36dp" + android:layout_height="36dp" /> <!-- need fixed size of the view since the source icon(HDPI) will be too large for phones --> <com.android.camera.ShutterButton android:id="@+id/shutter_button" diff --git a/res/layout/indicator_bar.xml b/res/layout/indicator_bar.xml new file mode 100644 index 0000000..b3d8c09 --- /dev/null +++ b/res/layout/indicator_bar.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<com.android.camera.ui.IndicatorControlContainer xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/indicator_control" + android:layout_width="48dp" + android:layout_height="match_parent" + android:layout_marginTop="6dp" + android:layout_marginRight="6dp" + android:layout_marginBottom="6dp" + android:clickable="true" + android:layout_alignParentRight="true"> + <com.android.camera.ui.IndicatorBar + android:id="@+id/indicator_bar" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <ImageView + android:id="@+id/zoom_control_icon" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:src="@drawable/btn_zoom_control" + android:visibility="gone" /> + <com.android.camera.ui.RotateImageView + android:id="@+id/second_level_indicator_bar_icon" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:src="@drawable/ic_settings_holo_light" /> + </com.android.camera.ui.IndicatorBar> + + <com.android.camera.ui.ZoomControlBar + android:id="@+id/zoom_control" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + <com.android.camera.ui.SecondLevelIndicatorBar + android:id="@+id/second_level_indicator_bar" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> +</com.android.camera.ui.IndicatorControlContainer> diff --git a/res/layout/preview_frame.xml b/res/layout/preview_frame.xml index 63887ff..1bf621a 100644 --- a/res/layout/preview_frame.xml +++ b/res/layout/preview_frame.xml @@ -53,12 +53,7 @@ android:layout_alignParentBottom="true" android:layout_margin="5dp" android:visibility="gone"/> - <com.android.camera.ui.IndicatorBar - android:id="@+id/indicator_control" - android:layout_width="48dp" - android:layout_height="match_parent" - android:layout_centerVertical="true" - android:layout_alignParentRight="true"/> <include layout="@layout/tap_to_focus_toast"/> + <include layout="@layout/indicator_bar" /> </RelativeLayout> </com.android.camera.PreviewFrameLayout> diff --git a/res/layout/preview_frame_video.xml b/res/layout/preview_frame_video.xml index 32154cd..abfd026 100644 --- a/res/layout/preview_frame_video.xml +++ b/res/layout/preview_frame_video.xml @@ -49,11 +49,6 @@ android:layout_height="match_parent" android:visibility="gone" android:background="@android:color/black" /> - <com.android.camera.ui.IndicatorBar - android:id="@+id/indicator_control" - android:layout_width="48dp" - android:layout_height="match_parent" - android:layout_centerVertical="true" - android:layout_alignParentRight="true"/> + <include layout="@layout/indicator_bar" /> </RelativeLayout> </com.android.camera.PreviewFrameLayout> diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java index 9d50fde..bd5d8d5 100644 --- a/src/com/android/camera/Camera.java +++ b/src/com/android/camera/Camera.java @@ -24,6 +24,7 @@ import com.android.camera.ui.RotateImageView; import com.android.camera.ui.RotateLayout; import com.android.camera.ui.SharePopup; import com.android.camera.ui.ZoomPicker; +import com.android.camera.ui.ZoomControl; import android.app.Activity; import android.content.BroadcastReceiver; @@ -92,7 +93,7 @@ import java.util.List; public class Camera extends ActivityBase implements View.OnClickListener, View.OnTouchListener, ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, ModePicker.OnModeChangeListener, - FaceDetectionListener { + FaceDetectionListener, CameraPreference.OnPreferenceChangedListener { private static final String TAG = "camera"; @@ -134,7 +135,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, private int mZoomValue; // The current zoom value. private int mZoomMax; private int mTargetZoomValue; - private ZoomPicker mZoomPicker; + private ZoomControl mZoomControl; private Parameters mParameters; private Parameters mInitialParams; @@ -477,17 +478,24 @@ public class Camera extends ActivityBase implements View.OnClickListener, } } + private void initializeZoomControl() { + mZoomControl = (ZoomControl) findViewById(R.id.zoom_control); + if (!mParameters.isZoomSupported()) { + mZoomControl.setZoomSupported(false); + } + mZoomControl.initialize(this); + } + private void initializeZoom() { if (!mParameters.isZoomSupported()) return; - mZoomMax = mParameters.getMaxZoom(); mSmoothZoomSupported = mParameters.isSmoothZoomSupported(); - if (mZoomPicker != null) { - mZoomPicker.setZoomMax(mZoomMax); - mZoomPicker.setZoomIndex(mParameters.getZoom()); - mZoomPicker.setSmoothZoomSupported(mSmoothZoomSupported); - mZoomPicker.setOnZoomChangeListener( - new ZoomPicker.OnZoomChangedListener() { + if (mZoomControl != null) { + mZoomControl.setZoomMax(mZoomMax); + mZoomControl.setZoomIndex(mParameters.getZoom()); + mZoomControl.setSmoothZoomSupported(mSmoothZoomSupported); + mZoomControl.setOnZoomChangeListener( + new ZoomControl.OnZoomChangedListener() { // only for immediate zoom @Override public void onZoomValueChanged(int index) { @@ -500,9 +508,9 @@ public class Camera extends ActivityBase implements View.OnClickListener, if (mPausing) return; Log.v(TAG, "zoom picker state=" + state); - if (state == ZoomPicker.ZOOM_IN) { + if (state == ZoomControl.ZOOM_IN) { Camera.this.onZoomValueChanged(mZoomMax); - } else if (state == ZoomPicker.ZOOM_OUT){ + } else if (state == ZoomControl.ZOOM_OUT){ Camera.this.onZoomValueChanged(0); } else { mTargetZoomValue = -1; @@ -514,7 +522,6 @@ public class Camera extends ActivityBase implements View.OnClickListener, } }); } - mCameraDevice.setZoomChangeListener(mZoomListener); } @@ -618,21 +625,13 @@ public class Camera extends ActivityBase implements View.OnClickListener, private void initializeCameraPicker() { mCameraPicker = (CameraPicker) findViewById(R.id.camera_picker); if (mCameraPicker != null) { - mCameraPicker.setImageResource(R.drawable.camera_toggle); ListPreference pref = mPreferenceGroup.findPreference( CameraSettings.KEY_CAMERA_ID); if (pref != null) { mCameraPicker.initialize(pref); - mCameraPicker.setListener(new MyCameraPickerListener()); + mCameraPicker.setListener(this); } - } - } - - private void initializeZoomPicker() { - View zoomIncrement = findViewById(R.id.zoom_increment); - View zoomDecrement = findViewById(R.id.zoom_decrement); - if (zoomIncrement != null && zoomDecrement != null && mParameters.isZoomSupported()) { - mZoomPicker = new ZoomPicker(this, zoomIncrement, zoomDecrement); + mCameraPicker.setCameraPickerIcon(); } } @@ -857,7 +856,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, mZoomValue = value; // Update the UI when we get zoom value. - if (mZoomPicker != null) mZoomPicker.setZoomIndex(value); + if (mZoomControl != null) mZoomControl.setZoomIndex(value); // Keep mParameters up to date. We do not getParameter again in // takePicture. If we do not do this, wrong zoom value will be set. @@ -1088,8 +1087,8 @@ public class Camera extends ActivityBase implements View.OnClickListener, // Do this after starting preview because it depends on camera // parameters. + initializeZoomControl(); initializeIndicatorControl(); - initializeZoomPicker(); initializeCameraPicker(); } @@ -1138,18 +1137,17 @@ public class Camera extends ActivityBase implements View.OnClickListener, CameraSettings.KEY_PICTURE_SIZE}; } else { SETTING_KEYS = new String[] { - CameraSettings.KEY_FLASH_MODE, - CameraSettings.KEY_WHITE_BALANCE}; + CameraSettings.KEY_WHITE_BALANCE, + CameraSettings.KEY_SCENE_MODE}; OTHER_SETTING_KEYS = new String[] { - CameraSettings.KEY_FOCUS_MODE, CameraSettings.KEY_EXPOSURE, - CameraSettings.KEY_SCENE_MODE, + CameraSettings.KEY_FOCUS_MODE, CameraSettings.KEY_PICTURE_SIZE, CameraSettings.KEY_RECORD_LOCATION}; } - mIndicatorControl.initialize(this, mPreferenceGroup, SETTING_KEYS, - OTHER_SETTING_KEYS); - mIndicatorControl.setListener(new MyIndicatorControlListener()); + mIndicatorControl.initialize(this, mPreferenceGroup, + CameraSettings.KEY_FLASH_MODE, SETTING_KEYS, OTHER_SETTING_KEYS); + mIndicatorControl.setListener(this); } private boolean collapseCameraControls() { @@ -1162,8 +1160,8 @@ public class Camera extends ActivityBase implements View.OnClickListener, private void enableCameraControls(boolean enable) { if (mIndicatorControl != null) mIndicatorControl.setEnabled(enable); if (mCameraPicker != null) mCameraPicker.setEnabled(enable); - if (mZoomPicker != null) mZoomPicker.setEnabled(enable); if (mModePicker != null) mModePicker.setEnabled(enable); + if (mZoomControl != null) mZoomControl.setEnabled(enable); } public static int roundOrientation(int orientation) { @@ -1206,6 +1204,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, if (mSharePopup != null) mSharePopup.setOrientation(degree); if (mIndicatorControl != null) mIndicatorControl.setDegree(degree); if (mCameraPicker != null) mCameraPicker.setDegree(degree); + if (mZoomControl != null) mZoomControl.setDegree(degree); } @Override @@ -2294,7 +2293,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, } } - private void onSharedPreferenceChanged() { + public void onSharedPreferenceChanged() { // ignore the events after "onPause()" if (mPausing) return; @@ -2346,7 +2345,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); } - protected void onRestorePreferencesClicked() { + public void onRestorePreferencesClicked() { if (mPausing) return; Runnable runnable = new Runnable() { public void run() { @@ -2364,7 +2363,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, if (mParameters.isZoomSupported()) { mZoomValue = 0; setCameraParametersWhenIdle(UPDATE_PARAM_ZOOM); - if (mZoomPicker != null) mZoomPicker.setZoomIndex(0); + if (mZoomControl != null) mZoomControl.setZoomIndex(0); } if (mIndicatorControl != null) { mIndicatorControl.dismissSettingPopup(); @@ -2375,7 +2374,7 @@ public class Camera extends ActivityBase implements View.OnClickListener, } } - protected void onOverriddenPreferencesClicked() { + public void onOverriddenPreferencesClicked() { if (mPausing) return; if (mNotSelectableToast == null) { String str = getResources().getString(R.string.not_selectable_in_scene_mode); @@ -2393,26 +2392,6 @@ public class Camera extends ActivityBase implements View.OnClickListener, mSharePopup.showAtLocation(mThumbnailView, Gravity.NO_GRAVITY, 0, 0); } - private class MyIndicatorControlListener implements IndicatorControl.Listener { - public void onSharedPreferenceChanged() { - Camera.this.onSharedPreferenceChanged(); - } - - public void onRestorePreferencesClicked() { - Camera.this.onRestorePreferencesClicked(); - } - - public void onOverriddenPreferencesClicked() { - Camera.this.onOverriddenPreferencesClicked(); - } - } - - private class MyCameraPickerListener implements CameraPicker.Listener { - public void onSharedPreferenceChanged() { - Camera.this.onSharedPreferenceChanged(); - } - } - @Override public void onFaceDetection(Face[] faces, android.hardware.Camera camera) { mFaceView.setFaces(faces); diff --git a/src/com/android/camera/CameraPreference.java b/src/com/android/camera/CameraPreference.java index 1a02070..04f3de0 100644 --- a/src/com/android/camera/CameraPreference.java +++ b/src/com/android/camera/CameraPreference.java @@ -33,6 +33,12 @@ public abstract class CameraPreference { private SharedPreferences mSharedPreferences; private final Context mContext; + static public interface OnPreferenceChangedListener { + public void onSharedPreferenceChanged(); + public void onRestorePreferencesClicked(); + public void onOverriddenPreferencesClicked(); + } + public CameraPreference(Context context, AttributeSet attrs) { mContext = context; TypedArray a = context.obtainStyledAttributes( diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java index d7e6da0..62f84b1 100644 --- a/src/com/android/camera/VideoCamera.java +++ b/src/com/android/camera/VideoCamera.java @@ -21,6 +21,7 @@ import com.android.camera.ui.IndicatorControl; import com.android.camera.ui.IndicatorWheel; import com.android.camera.ui.RotateImageView; import com.android.camera.ui.SharePopup; +import com.android.camera.ui.ZoomControl; import com.android.camera.ui.ZoomPicker; import android.content.ActivityNotFoundException; @@ -84,7 +85,7 @@ public class VideoCamera extends ActivityBase implements View.OnClickListener, ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener, - ModePicker.OnModeChangeListener { + ModePicker.OnModeChangeListener, CameraPreference.OnPreferenceChangedListener { private static final String TAG = "videocamera"; @@ -238,7 +239,7 @@ public class VideoCamera extends ActivityBase private int mZoomValue; // The current zoom value. private int mZoomMax; private int mTargetZoomValue; - private ZoomPicker mZoomPicker; + private ZoomControl mZoomControl; private final ZoomListener mZoomListener = new ZoomListener(); // front/back camera switch. @@ -448,29 +449,21 @@ public class VideoCamera extends ActivityBase mFrontCameraId = CameraHolder.instance().getFrontCameraId(); // Initialize after startPreview becuase this need mParameters. + initializeZoomControl(); initializeIndicatorControl(); - initializeZoomPicker(); initializeCameraPicker(); } - private void initializeZoomPicker() { - View zoomIncrement = findViewById(R.id.zoom_increment); - View zoomDecrement = findViewById(R.id.zoom_decrement); - if (zoomIncrement != null && zoomDecrement != null && mParameters.isZoomSupported()) { - mZoomPicker = new ZoomPicker(this, zoomIncrement, zoomDecrement); - } - } - private void initializeCameraPicker() { mCameraPicker = (CameraPicker) findViewById(R.id.camera_picker); if (mCameraPicker != null) { - mCameraPicker.setImageResource(R.drawable.camera_toggle_video); ListPreference pref = mPreferenceGroup.findPreference( CameraSettings.KEY_CAMERA_ID); if (pref != null) { mCameraPicker.initialize(pref); - mCameraPicker.setListener(new MyCameraPickerListener()); + mCameraPicker.setListener(this); } + mCameraPicker.setCameraPickerIcon(); } } @@ -508,13 +501,14 @@ public class VideoCamera extends ActivityBase } else { SETTING_KEYS = new String[] { CameraSettings.KEY_WHITE_BALANCE, - CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE, CameraSettings.KEY_VIDEO_QUALITY}; OTHER_SETTING_KEYS = new String[] { CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL}; } - mIndicatorControl.initialize(this, mPreferenceGroup, SETTING_KEYS, OTHER_SETTING_KEYS); - mIndicatorControl.setListener(new MyIndicatorControlListener()); + mIndicatorControl.initialize(this, mPreferenceGroup, + CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE, + SETTING_KEYS, OTHER_SETTING_KEYS); + mIndicatorControl.setListener(this); mPopupGestureDetector = new GestureDetector(this, new PopupGestureListener()); } @@ -840,7 +834,6 @@ public class VideoCamera extends ActivityBase mOnResumeTime = SystemClock.uptimeMillis(); mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100); } - initializeZoom(); } private void setPreviewDisplay(SurfaceHolder holder) { @@ -1749,7 +1742,10 @@ public class VideoCamera extends ActivityBase super.onConfigurationChanged(config); } - private void onRestorePreferencesClicked() { + public void onOverriddenPreferencesClicked() { + } + + public void onRestorePreferencesClicked() { Runnable runnable = new Runnable() { public void run() { restorePreferences(); @@ -1766,7 +1762,7 @@ public class VideoCamera extends ActivityBase if (mParameters.isZoomSupported()) { mZoomValue = 0; setCameraParameters(); - if (mZoomPicker != null) mZoomPicker.setZoomIndex(0); + if (mZoomControl != null) mZoomControl.setZoomIndex(0); } if (mIndicatorControl != null) { @@ -1778,7 +1774,7 @@ public class VideoCamera extends ActivityBase } } - private void onSharedPreferenceChanged() { + public void onSharedPreferenceChanged() { // ignore the events after "onPause()" or preview has not started yet if (mPausing) return; synchronized (mPreferences) { @@ -1837,19 +1833,6 @@ public class VideoCamera extends ActivityBase mSharePopup.showAtLocation(mThumbnailView, Gravity.NO_GRAVITY, 0, 0); } - private class MyIndicatorControlListener implements IndicatorControl.Listener { - public void onSharedPreferenceChanged() { - VideoCamera.this.onSharedPreferenceChanged(); - } - - public void onRestorePreferencesClicked() { - VideoCamera.this.onRestorePreferencesClicked(); - } - - public void onOverriddenPreferencesClicked() { - } - } - @Override public boolean dispatchTouchEvent(MotionEvent m) { // Check if the popup window should be dismissed first. @@ -1880,16 +1863,22 @@ public class VideoCamera extends ActivityBase } } - private void initializeZoom() { - if (!mParameters.isZoomSupported()) return; + private void initializeZoomControl() { + mZoomControl = (ZoomControl) findViewById(R.id.zoom_control); + if (!mParameters.isZoomSupported()) { + mZoomControl.setZoomSupported(false); + return; + } + mZoomControl.initialize(this); mZoomMax = mParameters.getMaxZoom(); mSmoothZoomSupported = mParameters.isSmoothZoomSupported(); - if (mZoomPicker != null) { - mZoomPicker.setZoomMax(mZoomMax); - mZoomPicker.setZoomIndex(mParameters.getZoom()); - mZoomPicker.setSmoothZoomSupported(mSmoothZoomSupported); - mZoomPicker.setOnZoomChangeListener( + if (mZoomControl != null) { + if (Util.isTabletUI()) ((ZoomPicker) mZoomControl).initialize(this); + mZoomControl.setZoomMax(mZoomMax); + mZoomControl.setZoomIndex(mParameters.getZoom()); + mZoomControl.setSmoothZoomSupported(mSmoothZoomSupported); + mZoomControl.setOnZoomChangeListener( new ZoomPicker.OnZoomChangedListener() { // only for immediate zoom @Override @@ -1929,7 +1918,7 @@ public class VideoCamera extends ActivityBase mZoomValue = value; // Update the UI when we get zoom value. - if (mZoomPicker != null) mZoomPicker.setZoomIndex(value); + if (mZoomControl != null) mZoomControl.setZoomIndex(value); // Keep mParameters up to date. We do not getParameter again in // takePicture. If we do not do this, wrong zoom value will be set. @@ -1967,10 +1956,4 @@ public class VideoCamera extends ActivityBase setCameraParameters(); } } - - private class MyCameraPickerListener implements CameraPicker.Listener { - public void onSharedPreferenceChanged() { - VideoCamera.this.onSharedPreferenceChanged(); - } - } } 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); } + } |