blob: d5fc0fad474b6a30dd9466a9a801e92cd91dfcc0 [file] [log] [blame]
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);
}
}