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