ShutterButton.java revision 8dc2b940fa574e22839c70ed0ee6ad6e903c2932
1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/* 2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License. 6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at 7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and 14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License. 15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera; 18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 19b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context; 20b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.AttributeSet; 21b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView; 22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/** 24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * A button designed to be used for the on-screen shutter button. 25271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * It's currently an {@code ImageView} that can call a delegate when the 26271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * pressed state changes. 27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 2830e2c49eedfbce51be7458161829a750f809d56dWu-cheng Lipublic class ShutterButton extends ImageView { 29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /** 30271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * A callback to be invoked when a ShutterButton's pressed state changes. 31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public interface OnShutterButtonListener { 33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /** 34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Called when a ShutterButton has been pressed. 35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 361bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li * @param pressed The ShutterButton that was pressed. 37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 381bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li void onShutterButtonFocus(boolean pressed); 391bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li void onShutterButtonClick(); 40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private OnShutterButtonListener mListener; 43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private boolean mOldPressed; 44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public ShutterButton(Context context, AttributeSet attrs) { 46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super(context, attrs); 47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void setOnShutterButtonListener(OnShutterButtonListener listener) { 50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mListener = listener; 51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /** 54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Hook into the drawable state changing to get changes to isPressed -- the 55e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang * onPressed listener doesn't always get called when the pressed state 56e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang * changes. 57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project protected void drawableStateChanged() { 60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.drawableStateChanged(); 61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project final boolean pressed = isPressed(); 62b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (pressed != mOldPressed) { 63b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (!pressed) { 64e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // When pressing the physical camera button the sequence of 65e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // events is: 66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // focus pressed, optional camera pressed, focus released. 67e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // We want to emulate this sequence of events with the shutter 68e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // button. When clicking using a trackball button, the view 698dc2b940fa574e22839c70ed0ee6ad6e903c2932Pin Ting // system changes the drawable state before posting click 70e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // notification, so the sequence of events is: 71b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // pressed(true), optional click, pressed(false) 72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // When clicking using touch events, the view system changes the 73e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // drawable state after posting click notification, so the 74e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // sequence of events is: 75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // pressed(true), pressed(false), optional click 76e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // Since we're emulating the physical camera button, we want to 77e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // have the same order of events. So we want the optional click 78e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // callback to be delivered before the pressed(false) callback. 79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // 80e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // To do this, we delay the posting of the pressed(false) event 81e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // slightly by pushing it on the event queue. This moves it 82e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // after the optional click notification, so our client always 83e38e6257ba032e80154c9a8a7ee62b6a98f02b8cChih-Chung Chang // sees events in this sequence: 84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // pressed(true), optional click, pressed(false) 85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project post(new Runnable() { 86913f3784d368a5e11fee5d5db2c355ef832685daWu-cheng Li @Override 87b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void run() { 88b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project callShutterButtonFocus(pressed); 89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }); 91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project callShutterButtonFocus(pressed); 93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mOldPressed = pressed; 95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void callShutterButtonFocus(boolean pressed) { 99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mListener != null) { 1001bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li mListener.onShutterButtonFocus(pressed); 101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean performClick() { 106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project boolean result = super.performClick(); 107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mListener != null) { 1081bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li mListener.onShutterButtonClick(); 109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return result; 111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project} 113