Home | History | Annotate | Download | only in camera
      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.text.method.Touch;
     21 import android.util.AttributeSet;
     22 import android.view.MotionEvent;
     23 import android.view.View;
     24 import android.widget.ImageView;
     25 
     26 import com.android.camera.debug.Log;
     27 import com.android.camera.ui.TouchCoordinate;
     28 
     29 import java.util.List;
     30 import java.util.ArrayList;
     31 
     32 /**
     33  * A button designed to be used for the on-screen shutter button.
     34  * It's currently an {@code ImageView} that can call a delegate when the
     35  * pressed state changes.
     36  */
     37 public class ShutterButton extends ImageView {
     38     private static final Log.Tag TAG = new Log.Tag("ShutterButton");
     39     public static final float ALPHA_WHEN_ENABLED = 1f;
     40     public static final float ALPHA_WHEN_DISABLED = 0.2f;
     41     private boolean mTouchEnabled = true;
     42     private TouchCoordinate mTouchCoordinate;
     43     /**
     44      * A callback to be invoked when a ShutterButton's pressed state changes.
     45      */
     46     public interface OnShutterButtonListener {
     47         /**
     48          * Called when a ShutterButton has been pressed.
     49          *
     50          * @param pressed The ShutterButton that was pressed.
     51          */
     52         void onShutterButtonFocus(boolean pressed);
     53         void onShutterCoordinate(TouchCoordinate coord);
     54         void onShutterButtonClick();
     55     }
     56 
     57     private List<OnShutterButtonListener> mListeners
     58         = new ArrayList<OnShutterButtonListener>();
     59     private boolean mOldPressed;
     60 
     61     public ShutterButton(Context context, AttributeSet attrs) {
     62         super(context, attrs);
     63     }
     64 
     65     /**
     66      * Add an {@link OnShutterButtonListener} to a set of listeners.
     67      */
     68     public void addOnShutterButtonListener(OnShutterButtonListener listener) {
     69         if (!mListeners.contains(listener)) {
     70             mListeners.add(listener);
     71         }
     72     }
     73 
     74     /**
     75      * Remove an {@link OnShutterButtonListener} from a set of listeners.
     76      */
     77     public void removeOnShutterButtonListener(OnShutterButtonListener listener) {
     78         if (mListeners.contains(listener)) {
     79             mListeners.remove(listener);
     80         }
     81     }
     82 
     83     @Override
     84     public boolean dispatchTouchEvent(MotionEvent m) {
     85         if (mTouchEnabled) {
     86             if (m.getActionMasked() == MotionEvent.ACTION_UP) {
     87                 mTouchCoordinate = new TouchCoordinate(m.getX(), m.getY(), this.getMeasuredWidth(),
     88                         this.getMeasuredHeight());
     89             }
     90             return super.dispatchTouchEvent(m);
     91         } else {
     92             return false;
     93         }
     94     }
     95 
     96     public void enableTouch(boolean enable) {
     97         mTouchEnabled = enable;
     98     }
     99 
    100     /**
    101      * Hook into the drawable state changing to get changes to isPressed -- the
    102      * onPressed listener doesn't always get called when the pressed state
    103      * changes.
    104      */
    105     @Override
    106     protected void drawableStateChanged() {
    107         super.drawableStateChanged();
    108         final boolean pressed = isPressed();
    109         if (pressed != mOldPressed) {
    110             if (!pressed) {
    111                 // When pressing the physical camera button the sequence of
    112                 // events is:
    113                 //    focus pressed, optional camera pressed, focus released.
    114                 // We want to emulate this sequence of events with the shutter
    115                 // button. When clicking using a trackball button, the view
    116                 // system changes the drawable state before posting click
    117                 // notification, so the sequence of events is:
    118                 //    pressed(true), optional click, pressed(false)
    119                 // When clicking using touch events, the view system changes the
    120                 // drawable state after posting click notification, so the
    121                 // sequence of events is:
    122                 //    pressed(true), pressed(false), optional click
    123                 // Since we're emulating the physical camera button, we want to
    124                 // have the same order of events. So we want the optional click
    125                 // callback to be delivered before the pressed(false) callback.
    126                 //
    127                 // To do this, we delay the posting of the pressed(false) event
    128                 // slightly by pushing it on the event queue. This moves it
    129                 // after the optional click notification, so our client always
    130                 // sees events in this sequence:
    131                 //     pressed(true), optional click, pressed(false)
    132                 post(new Runnable() {
    133                     @Override
    134                     public void run() {
    135                         callShutterButtonFocus(pressed);
    136                     }
    137                 });
    138             } else {
    139                 callShutterButtonFocus(pressed);
    140             }
    141             mOldPressed = pressed;
    142         }
    143     }
    144 
    145     private void callShutterButtonFocus(boolean pressed) {
    146         for (OnShutterButtonListener listener : mListeners) {
    147             listener.onShutterButtonFocus(pressed);
    148         }
    149     }
    150 
    151     @Override
    152     public boolean performClick() {
    153         boolean result = super.performClick();
    154         if (getVisibility() == View.VISIBLE) {
    155             for (OnShutterButtonListener listener : mListeners) {
    156                 listener.onShutterCoordinate(mTouchCoordinate);
    157                 mTouchCoordinate = null;
    158                 listener.onShutterButtonClick();
    159             }
    160         }
    161         return result;
    162     }
    163 }
    164