我的GWT应用程序使用DockLayoutPanel进行主要布局,页面本身不会滚动。我有一个带有MenuBar的PopupPanel,有时候当选择了MenuItem时,子菜单栏会突然从屏幕底部开始,迫使新滚动条进入浏览器并弄乱布局。
当默认定位将其从浏览器视口中移出(PopupPanel.showRelativeTo(uiTarget)定位的工作方式)时,如何让菜单弹出窗口表现良好并向上重新定位?
在查看MenuBar源代码时,看起来所有的布局都是在私有方法中完成的,所以我无法在子类中修复它,我也看不到任何我可以听到的事件会让我做重新定位自己。
答案 0 :(得分:3)
我们已经成功地使用这个策略了一段时间。
更新:还有一些工作要做。具体做法是:
创建一个reposition()方法,其中包括:
在onAttach()方法中,使用deferred命令调用reposition()方法。
答案 1 :(得分:1)
您可以在显示弹出窗口之前拦截弹出窗口,但是在创建弹出窗口大小之后。这样你就可以获得弹出窗口的宽度,并可以将其移动到另一个位置:
@Override
public void onContextMenu(ContextMenuEvent evt) {
int x = evt.getNativeEvent().getClientX();
int y = evt.getNativeEvent().getClientY();
popupMenu.setPopupPositionAndShow(new PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
if (x + offsetWidth > Window.getClientWidth()) {
x = Window.getClientWidth() - offsetWidth;
}
//use same technique for height if you want for y, then
setPosition(x, y);
}
});
}
(我知道这是一个老问题,但如果你搜索这个问题仍然会出现,所以我想提供现有解决方案)
答案 2 :(得分:0)
...电解金属锰
这是一个有趣的问题......
查看MenuBar源代码...尤其是方法 openPopup
private void openPopup(final MenuItem item) {
// Only the last popup to be opened should preview all event
if (parentMenu != null && parentMenu.popup != null) {
parentMenu.popup.setPreviewingAllNativeEvents(false);
}
// Create a new popup for this item, and position it next to
// the item (below if this is a horizontal menu bar, to the
// right if it's a vertical bar).
popup = new DecoratedPopupPanel(true, false, "menuPopup") {
{
setWidget(item.getSubMenu());
setPreviewingAllNativeEvents(true);
item.getSubMenu().onShow();
}
@Override
protected void onPreviewNativeEvent(NativePreviewEvent event) {
// Hook the popup panel's event preview. We use this to keep it from
// auto-hiding when the parent menu is clicked.
if (!event.isCanceled()) {
switch (event.getTypeInt()) {
case Event.ONMOUSEDOWN:
// If the event target is part of the parent menu, suppress the
// event altogether.
EventTarget target = event.getNativeEvent().getEventTarget();
Element parentMenuElement = item.getParentMenu().getElement();
if (parentMenuElement.isOrHasChild(Element.as(target))) {
event.cancel();
return;
}
super.onPreviewNativeEvent(event);
if (event.isCanceled()) {
selectItem(null);
}
return;
}
}
super.onPreviewNativeEvent(event);
}
};
popup.setAnimationType(AnimationType.ONE_WAY_CORNER);
popup.setAnimationEnabled(isAnimationEnabled);
popup.setStyleName(STYLENAME_DEFAULT + "Popup");
String primaryStyleName = getStylePrimaryName();
if (!STYLENAME_DEFAULT.equals(primaryStyleName)) {
popup.addStyleName(primaryStyleName + "Popup");
}
popup.addPopupListener(this);
shownChildMenu = item.getSubMenu();
item.getSubMenu().parentMenu = this;
// Show the popup, ensuring that the menubar's event preview remains on top
// of the popup's.
popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
public void setPosition(int offsetWidth, int offsetHeight) {
// depending on the bidi direction position a menu on the left or right
// of its base item
if (LocaleInfo.getCurrentLocale().isRTL()) {
if (vertical) {
popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - offsetWidth
+ 1, item.getAbsoluteTop());
} else {
popup.setPopupPosition(item.getAbsoluteLeft()
+ item.getOffsetWidth() - offsetWidth,
MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
- 1);
}
} else {
if (vertical) {
popup.setPopupPosition(MenuBar.this.getAbsoluteLeft()
+ MenuBar.this.getOffsetWidth() - 1, item.getAbsoluteTop());
} else {
popup.setPopupPosition(item.getAbsoluteLeft(),
MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
- 1);
}
}
}
});
}
将代码段指向
很有意思...
popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
public void setPosition(int offsetWidth, int offsetHeight) {
// depending on the bidi direction position a menu on the left or right
// of its base item
if (LocaleInfo.getCurrentLocale().isRTL()) {
if (vertical) {
popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - offsetWidth
+ 1, item.getAbsoluteTop());
} else {
popup.setPopupPosition(item.getAbsoluteLeft()
+ item.getOffsetWidth() - offsetWidth,
MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
- 1);
}
} else {
if (vertical) {
popup.setPopupPosition(MenuBar.this.getAbsoluteLeft()
+ MenuBar.this.getOffsetWidth() - 1, item.getAbsoluteTop());
} else {
popup.setPopupPosition(item.getAbsoluteLeft(),
MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
- 1);
}
}
}
});
...
...所以我可能会认为有一种感觉可以围绕MenuItem对象,尤其是其UIObject继承的方法,如getAbsoluteLeft()和getAbsoluteTop(),当然......
我建议以这种方式扩展MenuItem
//not tested
public class MyMenuItem extends MenuItem
{
private MenuBar aSubMenuBar;//ItemMenu's submenu
//...
@Override
public int getAbsoluteTop() {
// TODO Auto-generated method stub
return super.getAbsoluteTop()+movePopupTo();
}
private int movePopupTo()
{
int moveTo=0;
int bottom=RootPanel.getBodyElement().getAbsoluteBottom();
int rest=bottom -(super.getAbsoluteTop()+this.getaSubMenuBar().getOffsetHeight());
if(rest<0)
{
moveTo=rest;
}
return moveTo;
}
public MenuBar getaSubMenuBar() {
return aSubMenuBar;
}
public void setaSubMenuBar(MenuBar aSubMenuBar) {
this.aSubMenuBar = aSubMenuBar;
}
//...
}
这不是最终解决方案,而是基本概念。
报告是否有帮助
祝你好运