Stop overriding InputView.dispatchTouchEvent
Bug: 11721001 Bug: 11976254 Change-Id: I950f13ec4084da7fd9c1c25fd7abed1e5d31ed4cmain
parent
891e4860f8
commit
5cd732f8c5
|
@ -31,6 +31,7 @@ public final class InputView extends LinearLayout {
|
||||||
private final Rect mInputViewRect = new Rect();
|
private final Rect mInputViewRect = new Rect();
|
||||||
private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder;
|
private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder;
|
||||||
private MoreSuggestionsViewCanceler mMoreSuggestionsViewCanceler;
|
private MoreSuggestionsViewCanceler mMoreSuggestionsViewCanceler;
|
||||||
|
private MotionEventForwarder<?, ?> mActiveForwarder;
|
||||||
|
|
||||||
public InputView(final Context context, final AttributeSet attrs) {
|
public InputView(final Context context, final AttributeSet attrs) {
|
||||||
super(context, attrs, 0);
|
super(context, attrs, 0);
|
||||||
|
@ -53,42 +54,62 @@ public final class InputView extends LinearLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchTouchEvent(final MotionEvent me) {
|
public boolean onInterceptTouchEvent(final MotionEvent me) {
|
||||||
final Rect rect = mInputViewRect;
|
final Rect rect = mInputViewRect;
|
||||||
getGlobalVisibleRect(rect);
|
getGlobalVisibleRect(rect);
|
||||||
final int x = (int)me.getX() + rect.left;
|
final int index = me.getActionIndex();
|
||||||
final int y = (int)me.getY() + rect.top;
|
final int x = (int)me.getX(index) + rect.left;
|
||||||
|
final int y = (int)me.getY(index) + rect.top;
|
||||||
|
|
||||||
// The touch events that hit the top padding of keyboard should be
|
// The touch events that hit the top padding of keyboard should be forwarded to
|
||||||
// forwarded to {@link SuggestionStripView}.
|
// {@link SuggestionStripView}.
|
||||||
if (mKeyboardTopPaddingForwarder.dispatchTouchEvent(x, y, me)) {
|
if (mKeyboardTopPaddingForwarder.onInterceptTouchEvent(x, y, me)) {
|
||||||
|
mActiveForwarder = mKeyboardTopPaddingForwarder;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To cancel {@link MoreSuggestionsView}, we should intercept a touch event to
|
// To cancel {@link MoreSuggestionsView}, we should intercept a touch event to
|
||||||
// {@link MainKeyboardView} and dismiss the {@link MoreSuggestionsView}.
|
// {@link MainKeyboardView} and dismiss the {@link MoreSuggestionsView}.
|
||||||
if (mMoreSuggestionsViewCanceler.dispatchTouchEvent(x, y, me)) {
|
if (mMoreSuggestionsViewCanceler.onInterceptTouchEvent(x, y, me)) {
|
||||||
|
mActiveForwarder = mMoreSuggestionsViewCanceler;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.dispatchTouchEvent(me);
|
|
||||||
|
mActiveForwarder = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(final MotionEvent me) {
|
||||||
|
if (mActiveForwarder == null) {
|
||||||
|
return super.onTouchEvent(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Rect rect = mInputViewRect;
|
||||||
|
getGlobalVisibleRect(rect);
|
||||||
|
final int index = me.getActionIndex();
|
||||||
|
final int x = (int)me.getX(index) + rect.left;
|
||||||
|
final int y = (int)me.getY(index) + rect.top;
|
||||||
|
return mActiveForwarder.onTouchEvent(x, y, me);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class forwards series of {@link MotionEvent}s from <code>Forwarder</code> view to
|
* This class forwards series of {@link MotionEvent}s from <code>SenderView</code> to
|
||||||
* <code>Receiver</code> view.
|
* <code>ReceiverView</code>.
|
||||||
*
|
*
|
||||||
* @param <Sender> a {@link View} that may send a {@link MotionEvent} to <Receiver>.
|
* @param <SenderView> a {@link View} that may send a {@link MotionEvent} to <ReceiverView>.
|
||||||
* @param <Receiver> a {@link View} that receives forwarded {@link MotionEvent} from
|
* @param <ReceiverView> a {@link View} that receives forwarded {@link MotionEvent} from
|
||||||
* <Forwarder>.
|
* <SenderView>.
|
||||||
*/
|
*/
|
||||||
private static abstract class MotionEventForwarder<Sender extends View, Receiver extends View> {
|
private static abstract class
|
||||||
protected final Sender mSenderView;
|
MotionEventForwarder<SenderView extends View, ReceiverView extends View> {
|
||||||
protected final Receiver mReceiverView;
|
protected final SenderView mSenderView;
|
||||||
|
protected final ReceiverView mReceiverView;
|
||||||
|
|
||||||
private boolean mIsForwardingEvent;
|
|
||||||
protected final Rect mEventSendingRect = new Rect();
|
protected final Rect mEventSendingRect = new Rect();
|
||||||
protected final Rect mEventReceivingRect = new Rect();
|
protected final Rect mEventReceivingRect = new Rect();
|
||||||
|
|
||||||
public MotionEventForwarder(final Sender senderView, final Receiver receiverView) {
|
public MotionEventForwarder(final SenderView senderView, final ReceiverView receiverView) {
|
||||||
mSenderView = senderView;
|
mSenderView = senderView;
|
||||||
mReceiverView = receiverView;
|
mReceiverView = receiverView;
|
||||||
}
|
}
|
||||||
|
@ -96,12 +117,12 @@ public final class InputView extends LinearLayout {
|
||||||
// Return true if a touch event of global coordinate x, y needs to be forwarded.
|
// Return true if a touch event of global coordinate x, y needs to be forwarded.
|
||||||
protected abstract boolean needsToForward(final int x, final int y);
|
protected abstract boolean needsToForward(final int x, final int y);
|
||||||
|
|
||||||
// Translate global x-coordinate to <code>Receiver</code> local coordinate.
|
// Translate global x-coordinate to <code>ReceiverView</code> local coordinate.
|
||||||
protected int translateX(final int x) {
|
protected int translateX(final int x) {
|
||||||
return x - mEventReceivingRect.left;
|
return x - mEventReceivingRect.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate global y-coordinate to <code>Receiver</code> local coordinate.
|
// Translate global y-coordinate to <code>ReceiverView</code> local coordinate.
|
||||||
protected int translateY(final int y) {
|
protected int translateY(final int y) {
|
||||||
return y - mEventReceivingRect.top;
|
return y - mEventReceivingRect.top;
|
||||||
}
|
}
|
||||||
|
@ -109,49 +130,36 @@ public final class InputView extends LinearLayout {
|
||||||
// Callback when a {@link MotionEvent} is forwarded.
|
// Callback when a {@link MotionEvent} is forwarded.
|
||||||
protected void onForwardingEvent(final MotionEvent me) {}
|
protected void onForwardingEvent(final MotionEvent me) {}
|
||||||
|
|
||||||
// Dispatches a {@link MotioneEvent} to <code>Receiver</code> if needed and returns true.
|
// Returns true if a {@link MotionEvent} is needed to be forwarded to
|
||||||
// Otherwise returns false.
|
// <code>ReceiverView</code>. Otherwise returns false.
|
||||||
public boolean dispatchTouchEvent(final int x, final int y, final MotionEvent me) {
|
public boolean onInterceptTouchEvent(final int x, final int y, final MotionEvent me) {
|
||||||
// Forwards a {link MotionEvent} only if both <code>Sender</code> and
|
// Forwards a {link MotionEvent} only if both <code>SenderView</code> and
|
||||||
// <code>Receiver</code> are visible.
|
// <code>ReceiverView</code> are visible.
|
||||||
if (mSenderView.getVisibility() != View.VISIBLE ||
|
if (mSenderView.getVisibility() != View.VISIBLE ||
|
||||||
mReceiverView.getVisibility() != View.VISIBLE) {
|
mReceiverView.getVisibility() != View.VISIBLE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final Rect sendingRect = mEventSendingRect;
|
mSenderView.getGlobalVisibleRect(mEventSendingRect);
|
||||||
mSenderView.getGlobalVisibleRect(sendingRect);
|
if (!mEventSendingRect.contains(x, y)) {
|
||||||
if (!mIsForwardingEvent && !sendingRect.contains(x, y)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldForwardToReceiver = false;
|
if (me.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
|
// If the down event happens in the forwarding area, successive
|
||||||
switch (me.getActionMasked()) {
|
// {@link MotionEvent}s should be forwarded to <code>ReceiverView</code>.
|
||||||
case MotionEvent.ACTION_DOWN:
|
|
||||||
// If the down event happens in the forwarding area, successive {@link MotionEvent}s
|
|
||||||
// should be forwarded.
|
|
||||||
if (needsToForward(x, y)) {
|
if (needsToForward(x, y)) {
|
||||||
mIsForwardingEvent = true;
|
return true;
|
||||||
shouldForwardToReceiver = true;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
shouldForwardToReceiver = mIsForwardingEvent;
|
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_UP:
|
|
||||||
case MotionEvent.ACTION_CANCEL:
|
|
||||||
shouldForwardToReceiver = mIsForwardingEvent;
|
|
||||||
mIsForwardingEvent = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldForwardToReceiver) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final Rect receivingRect = mEventReceivingRect;
|
// Returns true if a {@link MotionEvent} is forwarded to <code>ReceiverView</code>.
|
||||||
mReceiverView.getGlobalVisibleRect(receivingRect);
|
// Otherwise returns false.
|
||||||
// Translate global coordinates to <code>Receiver</code> local coordinates.
|
public boolean onTouchEvent(final int x, final int y, final MotionEvent me) {
|
||||||
|
mReceiverView.getGlobalVisibleRect(mEventReceivingRect);
|
||||||
|
// Translate global coordinates to <code>ReceiverView</code> local coordinates.
|
||||||
me.setLocation(translateX(x), translateY(y));
|
me.setLocation(translateX(x), translateY(y));
|
||||||
mReceiverView.dispatchTouchEvent(me);
|
mReceiverView.dispatchTouchEvent(me);
|
||||||
onForwardingEvent(me);
|
onForwardingEvent(me);
|
||||||
|
@ -189,8 +197,7 @@ public final class InputView extends LinearLayout {
|
||||||
protected int translateY(final int y) {
|
protected int translateY(final int y) {
|
||||||
final int translatedY = super.translateY(y);
|
final int translatedY = super.translateY(y);
|
||||||
if (isInKeyboardTopPadding(y)) {
|
if (isInKeyboardTopPadding(y)) {
|
||||||
// The forwarded event should have coordinates that are inside of
|
// The forwarded event should have coordinates that are inside of the target.
|
||||||
// the target.
|
|
||||||
return Math.min(translatedY, mEventReceivingRect.height() - 1);
|
return Math.min(translatedY, mEventReceivingRect.height() - 1);
|
||||||
}
|
}
|
||||||
return translatedY;
|
return translatedY;
|
||||||
|
@ -200,8 +207,8 @@ public final class InputView extends LinearLayout {
|
||||||
/**
|
/**
|
||||||
* This class forwards {@link MotionEvent}s happened in the {@link MainKeyboardView} to
|
* This class forwards {@link MotionEvent}s happened in the {@link MainKeyboardView} to
|
||||||
* {@link SuggestionStripView} when the {@link MoreSuggestionsView} is showing.
|
* {@link SuggestionStripView} when the {@link MoreSuggestionsView} is showing.
|
||||||
* {@link SuggestionStripView} dismisses {@link MoreSuggestionsView} when it receives those
|
* {@link SuggestionStripView} dismisses {@link MoreSuggestionsView} when it receives any event
|
||||||
* events.
|
* outside of it.
|
||||||
*/
|
*/
|
||||||
private static class MoreSuggestionsViewCanceler
|
private static class MoreSuggestionsViewCanceler
|
||||||
extends MotionEventForwarder<MainKeyboardView, SuggestionStripView> {
|
extends MotionEventForwarder<MainKeyboardView, SuggestionStripView> {
|
||||||
|
|
Loading…
Reference in New Issue