Move forwarding code to ListPopupWindow, add drag-to-open in Spinner
BUG: 9437139 Change-Id: I4599cf65a472b2ce74d2301988359d87917a6eec
This commit is contained in:
@ -31,6 +31,8 @@ import android.view.ViewConfiguration;
|
||||
import android.view.View.MeasureSpec;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ListPopupWindow;
|
||||
import android.widget.ListPopupWindow.ForwardingListener;
|
||||
|
||||
import com.android.internal.view.ActionBarPolicy;
|
||||
import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
|
||||
@ -561,7 +563,36 @@ public class ActionMenuPresenter extends BaseMenuPresenter
|
||||
setFocusable(true);
|
||||
setVisibility(VISIBLE);
|
||||
setEnabled(true);
|
||||
setOnTouchListener(new OverflowForwardListener(context));
|
||||
|
||||
setOnTouchListener(new ForwardingListener(context) {
|
||||
@Override
|
||||
public ListPopupWindow getPopup() {
|
||||
if (mOverflowPopup == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mOverflowPopup.getPopup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onForwardingStarted() {
|
||||
showOverflowMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onForwardingStopped() {
|
||||
// Displaying the popup occurs asynchronously, so wait for
|
||||
// the runnable to finish before deciding whether to stop
|
||||
// forwarding.
|
||||
if (mPostedOpenRunnable != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hideOverflowMenu();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -680,56 +711,4 @@ public class ActionMenuPresenter extends BaseMenuPresenter
|
||||
mPostedOpenRunnable = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class OverflowForwardListener extends TouchForwardingListener {
|
||||
/** Scaled touch slop, used for detecting movement outside bounds. */
|
||||
private final float mScaledTouchSlop;
|
||||
|
||||
private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;
|
||||
|
||||
public OverflowForwardListener(Context context) {
|
||||
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchObserved(View src, MotionEvent srcEvent) {
|
||||
if (!src.isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always start forwarding events when the source view is touched.
|
||||
mActivePointerId = srcEvent.getPointerId(0);
|
||||
src.performClick();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchForwarded(View src, MotionEvent srcEvent) {
|
||||
final OverflowPopup popup = mOverflowPopup;
|
||||
if (popup != null && popup.isShowing()) {
|
||||
final int activePointerId = mActivePointerId;
|
||||
if (activePointerId != MotionEvent.INVALID_POINTER_ID && src.isEnabled()
|
||||
&& popup.forwardMotionEvent(src, srcEvent, activePointerId)) {
|
||||
// Handled the motion event, continue forwarding.
|
||||
return true;
|
||||
}
|
||||
|
||||
final int activePointerIndex = srcEvent.findPointerIndex(activePointerId);
|
||||
if (activePointerIndex >= 0) {
|
||||
final float x = srcEvent.getX(activePointerIndex);
|
||||
final float y = srcEvent.getY(activePointerIndex);
|
||||
if (src.pointInView(x, y, mScaledTouchSlop)) {
|
||||
// The user is touching the source view. Cancel
|
||||
// forwarding, but don't dismiss the popup.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
popup.dismiss();
|
||||
}
|
||||
|
||||
// Cancel forwarding.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,10 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
|
||||
}
|
||||
}
|
||||
|
||||
public ListPopupWindow getPopup() {
|
||||
return mPopup;
|
||||
}
|
||||
|
||||
public boolean tryShow() {
|
||||
mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle);
|
||||
mPopup.setOnDismissListener(this);
|
||||
@ -159,22 +163,6 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
|
||||
return mPopup != null && mPopup.isShowing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards motion events from a source view to the popup window.
|
||||
*
|
||||
* @param src view from which the event was forwarded
|
||||
* @param event forwarded motion event in source-local coordinates
|
||||
* @param activePointerId id of the pointer that activated forwarding
|
||||
* @return whether the event was handled
|
||||
*/
|
||||
public boolean forwardMotionEvent(View src, MotionEvent event, int activePointerId) {
|
||||
if (mPopup == null || !mPopup.isShowing()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mPopup.onForwardedEvent(src, event, activePointerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
MenuAdapter adapter = mAdapter;
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.view.menu;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Touch listener used to intercept touches and forward them out of a view.
|
||||
*/
|
||||
abstract class TouchForwardingListener implements View.OnTouchListener {
|
||||
/** Whether this listener is currently forwarding touch events. */
|
||||
private boolean mForwarding;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent ev) {
|
||||
final int actionMasked = ev.getActionMasked();
|
||||
|
||||
if (mForwarding) {
|
||||
// Rejecting the event or ending the stream stops forwarding.
|
||||
if (!onTouchForwarded(v, ev) || actionMasked == MotionEvent.ACTION_UP
|
||||
|| actionMasked == MotionEvent.ACTION_CANCEL) {
|
||||
stopForwarding();
|
||||
}
|
||||
} else {
|
||||
if (onTouchObserved(v, ev)) {
|
||||
startForwarding();
|
||||
}
|
||||
}
|
||||
|
||||
return mForwarding;
|
||||
}
|
||||
|
||||
public void startForwarding() {
|
||||
mForwarding = true;
|
||||
}
|
||||
|
||||
public void stopForwarding() {
|
||||
mForwarding = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to start forwarding motion events.
|
||||
*
|
||||
* @param v The view that triggered forwarding.
|
||||
* @return True to start forwarding motion events, or false to cancel.
|
||||
*/
|
||||
public abstract boolean onTouchObserved(View v, MotionEvent ev);
|
||||
|
||||
/**
|
||||
* Handles forwarded motion events.
|
||||
*
|
||||
* @param v The view from which the event was forwarded.
|
||||
* @param ev The forwarded motion event.
|
||||
* @return True to continue forwarding motion events, or false to cancel.
|
||||
*/
|
||||
public abstract boolean onTouchForwarded(View v, MotionEvent ev);
|
||||
}
|
Reference in New Issue
Block a user