PopupPanel是GWT写的(akhem)很久以前的一个类(这就是为什么它太糟糕了),允许弹出内容的弹出窗口.其中一个选项是autoHide,如果在弹出窗口之外有某个事件,它会关闭弹出窗口.除了Safari Mobil(
具体来说,代码说:
case Event.ONMOUSEDOWN: ... if (!eventTargetsPopupOrPartner && autoHide) { hide(true); ...
显然这不完整,它还应该包括Event.ONTOUCHSTART
问题是,所有方法和字段都是私有的,所以我无法添加此功能.这是GWT团队的一个大嘘声,但并不是真正的关注,因为我可以创建自己的类并复制PopupPanel的内容.最大的问题是nativeEventPreview没有捕获Touch事件!
我尝试将以下内容添加到事件预览中:
private static NativePreviewHandler nativePreviewHandler = new NativePreviewHandler() { public void onPreviewNativeEvent(NativePreviewEvent event) { Event nativeEvent = Event.as(event.getNativeEvent()); switch (nativeEvent.getTypeInt()) { case Event.ONTOUCHSTART: case Event.ONMOUSEDOWN: EventTarget target = nativeEvent.getEventTarget(); if (!Element.is(target) || !popup.getElement().isOrHasChild(Element.as(target))) { popup.hide(); } break; } } };
‘弹出窗口’是PopupPanel,我试图关闭外部触摸事件.
令人遗憾的是,在地球上的任何其他浏览器中进行测试时,它可以用于鼠标按下,但不适用于iPad.
我尝试的另一件事是在PopupPanel的玻璃上添加一个TouchStartHandler(它背后的灰色外观).我希望我可以通过这种方式捕捉触摸事件,但我无法在玻璃上触发事件,因为它以某种有趣的方式附加到DOM.我的代码:
private static class ProperPopupPanel extends PopupPanel { public ProperPopupPanel() { super(); } void setHideOnGlassTouch() { setGlassEnabled(true); TouchableLabeThatDoesntCrashOnWrap glass = new TouchableLabeThatDoesntCrashOnWrap(getGlassElement()); glass.addTouchStartHandler(new TouchStartHandler() { @Override public void onTouchStart(TouchStartEvent event) { hide(); } }); glass.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { hide(); } }); } private class TouchableLabeThatDoesntCrashOnWrap extends Label { public TouchableLabeThatDoesntCrashOnWrap(Element element) { super(element); super.onAttach(); } } }
在我看来,这应该有效,但事实并非如此.我不知道为什么.欢迎任何想法或建议.谢谢.
这里没有足够的GWT用户……我创建了自己的类,通过JSNI添加触摸处理程序…/** * Overwrite of the usual PopupPanel with a modification that this one * works well on touch-enabled browsers. * @author McTrafik */ public class ProperPopupPanel extends PopupPanel { //////////////////////////////////////////////////////////// /////////// OVERRIDES ////////////////////////////////////// //////////////////////////////////////////////////////////// public ProperPopupPanel() { super(); setTouchListener(); } @Override public void hide() { super.hide(); removeTouchListener(); } @Override public void show() { super.show(); addTouchListener(); } //////////////////////////////////////////////////////////// /////////// NANDLERS /////////////////////////////////////// //////////////////////////////////////////////////////////// protected JavaScriptObject touchHandler; /** * Handle a touch event that happened while the popup is open. * @param event - The event to handle */ protected void handleTouchEvent(Event event) { // Check to see if the events should be firing in the first place. if (!isShowing()) { removeTouchListener(); return; } // Check if the event happened within the popup EventTarget target = event.getEventTarget(); if (!Element.is(target) || !getElement().isOrHasChild(Element.as(target))) { // Stop event if the popup is modal if (isModal()) event.preventDefault(); // Close the popup if the event happened outside if (isAutoHideEnabled()) { hide(true); removeTouchListener(); } } }; /** * Create a touchHandler that knows how to point to this instance. * Without it there's a cast exception that happens. */ protected native void setTouchListener() /*-{ var caller = this; this.@[package].ProperPopupPanel::touchHandler = function(event) { caller.@[package].ProperPopupPanel::handleTouchEvent(Lcom/google/gwt/user/client/Event;)(event); } }-*/; /** * Add a touch listener that will listen to touch events. */ protected native void addTouchListener() /*-{ $doc.addEventListener( "touchstart", this.@[package].ProperPopupPanel::touchHandler, true ); $doc.addEventListener( "MozTouchDown", this.@[package].ProperPopupPanel::touchHandler, true ); }-*/; /** * Remove the touch listeners */ protected native void removeTouchListener() /*-{ $doc.removeEventListener( "touchstart", this.@[package].ProperPopupPanel::touchHandler, true ); $doc.removeEventListener( "MozTouchDown", this.@[package].ProperPopupPanel::touchHandler, true ); }-*/; }