Home | History | Annotate | Download | only in launcher3
      1 package com.android.launcher3;
      2 
      3 import android.view.MotionEvent;
      4 import android.view.View;
      5 import android.view.ViewConfiguration;
      6 
      7 /**
      8  * Helper for identifying when a stylus touches a view while the primary stylus button is pressed.
      9  * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}.
     10  */
     11 public class StylusEventHelper {
     12 
     13     /**
     14      * Implement this interface to receive callbacks for a stylus button press and release.
     15      */
     16     public interface StylusButtonListener {
     17         /**
     18          * Called when the stylus button is pressed.
     19          *
     20          * @param event The MotionEvent that the button press occurred for.
     21          * @return Whether the event was handled.
     22          */
     23         public boolean onPressed(MotionEvent event);
     24 
     25         /**
     26          * Called when the stylus button is released after a button press. This is also called if
     27          * the event is canceled or the stylus is lifted off the screen.
     28          *
     29          * @param event The MotionEvent the button release occurred for.
     30          * @return Whether the event was handled.
     31          */
     32         public boolean onReleased(MotionEvent event);
     33     }
     34 
     35     private boolean mIsButtonPressed;
     36     private View mView;
     37     private StylusButtonListener mListener;
     38     private final float mSlop;
     39 
     40     /**
     41      * Constructs a helper for listening to stylus button presses and releases. Ensure that {
     42      * {@link #onMotionEvent(MotionEvent)} and {@link #onGenericMotionEvent(MotionEvent)} are called on
     43      * the helper to correctly identify stylus events.
     44      *
     45      * @param listener The listener to call for stylus events.
     46      * @param view Optional view associated with the touch events.
     47      */
     48     public StylusEventHelper(StylusButtonListener listener, View view) {
     49         mListener = listener;
     50         mView = view;
     51         if (mView != null) {
     52             mSlop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
     53         } else {
     54             mSlop = ViewConfiguration.getTouchSlop();
     55         }
     56     }
     57 
     58     public boolean onMotionEvent(MotionEvent event) {
     59         final boolean stylusButtonPressed = isStylusButtonPressed(event);
     60         switch (event.getAction()) {
     61             case MotionEvent.ACTION_DOWN:
     62                 mIsButtonPressed = stylusButtonPressed;
     63                 if (mIsButtonPressed) {
     64                     return mListener.onPressed(event);
     65                 }
     66                 break;
     67             case MotionEvent.ACTION_MOVE:
     68                 if (!Utilities.pointInView(mView, event.getX(), event.getY(), mSlop)) {
     69                     return false;
     70                 }
     71                 if (!mIsButtonPressed && stylusButtonPressed) {
     72                     mIsButtonPressed = true;
     73                     return mListener.onPressed(event);
     74                 } else if (mIsButtonPressed && !stylusButtonPressed) {
     75                     mIsButtonPressed = false;
     76                     return mListener.onReleased(event);
     77                 }
     78                 break;
     79             case MotionEvent.ACTION_UP:
     80             case MotionEvent.ACTION_CANCEL:
     81                 if (mIsButtonPressed) {
     82                     mIsButtonPressed = false;
     83                     return mListener.onReleased(event);
     84                 }
     85                 break;
     86         }
     87         return false;
     88     }
     89 
     90     /**
     91      * Whether a stylus button press is occurring.
     92      */
     93     public boolean inStylusButtonPressed() {
     94         return mIsButtonPressed;
     95     }
     96 
     97     /**
     98      * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
     99      * pressed.
    100      *
    101      * @param event The event to check.
    102      * @return Whether a stylus button press occurred.
    103      */
    104     private static boolean isStylusButtonPressed(MotionEvent event) {
    105         return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
    106                 && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY)
    107                         == MotionEvent.BUTTON_SECONDARY);
    108     }
    109 }