| package com.android.launcher3; |
| |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.ViewConfiguration; |
| |
| /** |
| * Helper for identifying when a stylus touches a view while the primary stylus button is pressed. |
| * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}. |
| */ |
| public class StylusEventHelper { |
| |
| /** |
| * Implement this interface to receive callbacks for a stylus button press and release. |
| */ |
| public interface StylusButtonListener { |
| /** |
| * Called when the stylus button is pressed. |
| * |
| * @param event The MotionEvent that the button press occurred for. |
| * @return Whether the event was handled. |
| */ |
| public boolean onPressed(MotionEvent event); |
| |
| /** |
| * Called when the stylus button is released after a button press. This is also called if |
| * the event is canceled or the stylus is lifted off the screen. |
| * |
| * @param event The MotionEvent the button release occurred for. |
| * @return Whether the event was handled. |
| */ |
| public boolean onReleased(MotionEvent event); |
| } |
| |
| private boolean mIsButtonPressed; |
| private View mView; |
| private StylusButtonListener mListener; |
| private final float mSlop; |
| |
| /** |
| * Constructs a helper for listening to stylus button presses and releases. Ensure that { |
| * {@link #onMotionEvent(MotionEvent)} and {@link #onGenericMotionEvent(MotionEvent)} are called on |
| * the helper to correctly identify stylus events. |
| * |
| * @param listener The listener to call for stylus events. |
| * @param view Optional view associated with the touch events. |
| */ |
| public StylusEventHelper(StylusButtonListener listener, View view) { |
| mListener = listener; |
| mView = view; |
| if (mView != null) { |
| mSlop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop(); |
| } else { |
| mSlop = ViewConfiguration.getTouchSlop(); |
| } |
| } |
| |
| public boolean onMotionEvent(MotionEvent event) { |
| final boolean stylusButtonPressed = isStylusButtonPressed(event); |
| switch (event.getAction()) { |
| case MotionEvent.ACTION_DOWN: |
| mIsButtonPressed = stylusButtonPressed; |
| if (mIsButtonPressed) { |
| return mListener.onPressed(event); |
| } |
| break; |
| case MotionEvent.ACTION_MOVE: |
| if (!Utilities.pointInView(mView, event.getX(), event.getY(), mSlop)) { |
| return false; |
| } |
| if (!mIsButtonPressed && stylusButtonPressed) { |
| mIsButtonPressed = true; |
| return mListener.onPressed(event); |
| } else if (mIsButtonPressed && !stylusButtonPressed) { |
| mIsButtonPressed = false; |
| return mListener.onReleased(event); |
| } |
| break; |
| case MotionEvent.ACTION_UP: |
| case MotionEvent.ACTION_CANCEL: |
| if (mIsButtonPressed) { |
| mIsButtonPressed = false; |
| return mListener.onReleased(event); |
| } |
| break; |
| } |
| return false; |
| } |
| |
| /** |
| * Whether a stylus button press is occurring. |
| */ |
| public boolean inStylusButtonPressed() { |
| return mIsButtonPressed; |
| } |
| |
| /** |
| * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button |
| * pressed. |
| * |
| * @param event The event to check. |
| * @return Whether a stylus button press occurred. |
| */ |
| private static boolean isStylusButtonPressed(MotionEvent event) { |
| return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS |
| && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) |
| == MotionEvent.BUTTON_SECONDARY); |
| } |
| } |