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.util.AttributeSet;
     21 import android.view.MotionEvent;
     22 import android.widget.ImageView;
     23 
     24 /**
     25  * A button designed to be used for the on-screen shutter button.
     26  * It's currently an {@code ImageView} that can call a delegate when the
     27  * pressed state changes.
     28  */
     29 public class ShutterButton extends ImageView {
     30 
     31     private boolean mTouchEnabled = true;
     32 
     33     /**
     34      * A callback to be invoked when a ShutterButton's pressed state changes.
     35      */
     36     public interface OnShutterButtonListener {
     37         /**
     38          * Called when a ShutterButton has been pressed.
     39          *
     40          * @param pressed The ShutterButton that was pressed.
     41          */
     42         void onShutterButtonFocus(boolean pressed);
     43         void onShutterButtonClick();
     44     }
     45 
     46     private OnShutterButtonListener mListener;
     47     private boolean mOldPressed;
     48 
     49     public ShutterButton(Context context, AttributeSet attrs) {
     50         super(context, attrs);
     51     }
     52 
     53     public void setOnShutterButtonListener(OnShutterButtonListener listener) {
     54         mListener = listener;
     55     }
     56 
     57     @Override
     58     public boolean dispatchTouchEvent(MotionEvent m) {
     59         if (mTouchEnabled) {
     60             return super.dispatchTouchEvent(m);
     61         } else {
     62             return false;
     63         }
     64     }
     65 
     66     public void enableTouch(boolean enable) {
     67         mTouchEnabled = enable;
     68     }
     69 
     70     /**
     71      * Hook into the drawable state changing to get changes to isPressed -- the
     72      * onPressed listener doesn't always get called when the pressed state
     73      * changes.
     74      */
     75     @Override
     76     protected void drawableStateChanged() {
     77         super.drawableStateChanged();
     78         final boolean pressed = isPressed();
     79         if (pressed != mOldPressed) {
     80             if (!pressed) {
     81                 // When pressing the physical camera button the sequence of
     82                 // events is:
     83                 //    focus pressed, optional camera pressed, focus released.
     84                 // We want to emulate this sequence of events with the shutter
     85                 // button. When clicking using a trackball button, the view
     86                 // system changes the drawable state before posting click
     87                 // notification, so the sequence of events is:
     88                 //    pressed(true), optional click, pressed(false)
     89                 // When clicking using touch events, the view system changes the
     90                 // drawable state after posting click notification, so the
     91                 // sequence of events is:
     92                 //    pressed(true), pressed(false), optional click
     93                 // Since we're emulating the physical camera button, we want to
     94                 // have the same order of events. So we want the optional click
     95                 // callback to be delivered before the pressed(false) callback.
     96                 //
     97                 // To do this, we delay the posting of the pressed(false) event
     98                 // slightly by pushing it on the event queue. This moves it
     99                 // after the optional click notification, so our client always
    100                 // sees events in this sequence:
    101                 //     pressed(true), optional click, pressed(false)
    102                 post(new Runnable() {
    103                     @Override
    104                     public void run() {
    105                         callShutterButtonFocus(pressed);
    106                     }
    107                 });
    108             } else {
    109                 callShutterButtonFocus(pressed);
    110             }
    111             mOldPressed = pressed;
    112         }
    113     }
    114 
    115     private void callShutterButtonFocus(boolean pressed) {
    116         if (mListener != null) {
    117             mListener.onShutterButtonFocus(pressed);
    118         }
    119     }
    120 
    121     @Override
    122     public boolean performClick() {
    123         boolean result = super.performClick();
    124         if (mListener != null) {
    125             mListener.onShutterButtonClick();
    126         }
    127         return result;
    128     }
    129 }
    130