2012-03-15 98 views
1

我有一個面板的大小需要更改以獲得更好的視圖,因爲我在其中加載了很多不同的小部件。我繼續在GWT中使用可調整大小的面板。它一切正常。在GWT中觸摸事件調整大小面板

我的問題是:我如何能實現它的觸摸功能的設備如Android平板電腦,ipad公司等

調整大小面板使用鼠標拖動事件,我希望。那麼,我如何才能實現觸摸事件的相同。

我見過GWT-DND API,它提供Resibale Panels,並且在Touch中工作。

但是,如果我使用它,這將是一個更乏味的任務。

任何人都可以幫忙嗎?

回答

2

最後我想通了。這是相當簡單的,只是增加了觸摸處理程序類似於我使用的鼠標事件。

  • ONTOUCHSTART = onmousedown事件
  • ONTOUCHMOVE =的OnMouseMove
  • ONTOUCHEND = ONMOUSEUP
  • ONTOUCHCANCEL = ONLOSECAPTURE

ResizePanel.java

/** 
* Abstract base class for {@link VerticalResizePanel}. 
*/ 
abstract class ResizePanel extends Panel implements HasResizeHandlers { 

    /* **************************************** */ 
    // Private Static Fields 
    /* **************************************** */ 
    /** 
    * The element that masks the screen so we can catch mouse events over 
    * iframes. 
    */ 
    private static Element glassElem = null; 

    /** The handler manager for our events. */ 

    /* **************************************** */ 
    // Private Fields 
    /* **************************************** */ 
    // The elements containing the widgets. 
    /** The elements. */ 
    private final Element[] elements = new Element[1]; 

    /** The handler manager for our events. */ 

    private final EventBus resizeHandlerManager = new SimpleEventBus(); 

    // Indicates whether drag resizing is active. 
    /** The is resizing. */ 
    private boolean isResizing = false; 

    // The element that acts as the splitter. 
    /** The split elem. */ 
    private final Element splitElem; 

    // The enclosed widgets. 
    /** The widgets. */ 
    private final Widget[] widgets = new Widget[2]; 

    /* **************************************** */ 
    // Constructors 
    /* **************************************** */ 
    /** 
    * Initializes the split panel. 
    * 
    * @param mainElem 
    *   the root element for the split panel 
    * @param splitElem 
    *   the element that acts as the splitter 
    * @param headElem 
    *   the element to contain the top or left most widget 
    */ 
    ResizePanel(final Element mainElem, final Element splitElem,final Element headElem) { 
     this.setElement(mainElem); 
     this.splitElem = splitElem; 
     this.elements[0] = headElem; 
     this.sinkEvents(Event.MOUSEEVENTS | Event.ONLOSECAPTURE | Event.TOUCHEVENTS | Event.ONTOUCHCANCEL); 
     if (ResizePanel.glassElem == null) { 
      ResizePanel.glassElem = DOM.createDiv(); 
      ResizePanel.glassElem.getStyle() 
        .setProperty("position", "absolute"); 
      ResizePanel.glassElem.getStyle().setProperty("top", "0px"); 
      ResizePanel.glassElem.getStyle().setProperty("left", "0px"); 
      ResizePanel.glassElem.getStyle().setProperty("margin", "0px"); 
      ResizePanel.glassElem.getStyle().setProperty("padding", "0px"); 
      ResizePanel.glassElem.getStyle().setProperty("border", "0px"); 
      // We need to set the background color or mouse events will go right 
      // through the glassElem. If the SplitPanel contains an iframe, the 
      // iframe will capture the event and the slider will stop moving. 
      ResizePanel.glassElem.getStyle().setProperty("background", "white"); 
      ResizePanel.glassElem.getStyle().setProperty("opacity", "0.0"); 
      ResizePanel.glassElem.getStyle().setProperty("filter", 
        "alpha(opacity=0)"); 
      ResizePanel.glassElem.setId("glassElementId"); 
     } 
    } 

    /* **************************************** */ 
    // Package Static Properties 
    /* **************************************** */ 
    /** 
    * Returns the offsetHeight element property. 
    * 
    * @param elem 
    *   the element 
    * @return the offsetHeight property 
    */ 
    static final int getOffsetHeight(final Element elem) { 
     return DOM.getElementPropertyInt(elem, "offsetHeight"); 
    } 

    /** 
    * Returns the offsetWidth element property. 
    * 
    * @param elem 
    *   the element 
    * @return the offsetWidth property 
    */ 
    static final int getOffsetWidth(final Element elem) { 
     return DOM.getElementPropertyInt(elem, "offsetWidth"); 
    } 

    /** 
    * Adds zero or none CSS values for padding, margin and border to prevent 
    * stylesheet overrides. Returns the element for convenience to support 
    * builder pattern. 
    * 
    * @param elem 
    *   the element 
    * @return the element 
    */ 
    static final Element preventBoxStyles(final Element elem) { 
     DOM.setIntStyleAttribute(elem, "padding", 0); 
     DOM.setIntStyleAttribute(elem, "margin", 0); 
     DOM.setStyleAttribute(elem, "border", "none"); 
     return elem; 
    } 

    /** 
    * Convenience method to set bottom offset of an element. 
    * 
    * @param elem 
    *   the element 
    * @param size 
    *   a CSS length value for bottom 
    */ 
    static void setBottom(final Element elem, final String size) { 
     DOM.setStyleAttribute(elem, "bottom", size); 
    } 

    /** 
    * Sets the elements css class name. 
    * 
    * @param elem 
    *   the element 
    * @param className 
    *   the class name 
    */ 
    static final void setClassname(final Element elem, final String className) { 
     DOM.setElementProperty(elem, "className", className); 
    } 

    /** 
    * Convenience method to set the height of an element. 
    * 
    * @param elem 
    *   the element 
    * @param height 
    *   a CSS length value for the height 
    */ 
    static final void setHeight(final Element elem, final String height) { 
     DOM.setStyleAttribute(elem, "height", height); 
    } 

    /** 
    * Convenience method to set the left offset of an element. 
    * 
    * @param elem 
    *   the element 
    * @param left 
    *   a CSS length value for left 
    */ 
    static final void setLeft(final Element elem, final String left) { 
     DOM.setStyleAttribute(elem, "left", left); 
    } 

    /** 
    * Convenience method to set the right offset of an element. 
    * 
    * @param elem 
    *   the element 
    * @param right 
    *   a CSS length value for right 
    */ 
    static final void setRight(final Element elem, final String right) { 
     DOM.setStyleAttribute(elem, "right", right); 
    } 

    /** 
    * Convenience method to set the top offset of an element. 
    * 
    * @param elem 
    *   the element 
    * @param top 
    *   a CSS length value for top 
    */ 
    static final void setTop(final Element elem, final String top) { 
     DOM.setStyleAttribute(elem, "top", top); 
    } 

    /** 
    * Convenience method to set the width of an element. 
    * 
    * @param elem 
    *   the element 
    * @param width 
    *   a CSS length value for the width 
    */ 
    static final void setWidth(final Element elem, final String width) { 
     DOM.setStyleAttribute(elem, "width", width); 
    } 

    /* **************************************** */ 
    // Public Properties 
    /* **************************************** */ 
    /** 
    * Gets the element that is acting as the splitter. 
    * 
    * @return the element 
    */ 
    public Element getSplitElement() { 
     return this.splitElem; 
    } 

    /** 
    * Gets the value of resizeHandlerManager. 
    * 
    * @return Gets the value of resizeHandlerManager. 
    */ 
    public EventBus getResizeHandlerManager() { 
     return resizeHandlerManager; 
    } 

    /** 
    * Indicates whether the split panel is being resized. 
    * 
    * @return if the user is dragging the splitter, otherwise 
    */ 
    public boolean isResizing() { 
     return this.isResizing; 
    } 

    /* **************************************** */ 
    // Public Static Methods 
    /* **************************************** */ 
    /** 
    * Sets an elements positioning to absolute. 
    * 
    * @param elem 
    *   the element 
    */ 
    static void addAbsolutePositoning(final Element elem) { 
     DOM.setStyleAttribute(elem, "position", "absolute"); 
    } 

    /** 
    * Adds clipping to an element. 
    * 
    * @param elem 
    *   the element 
    */ 
    static final void addClipping(final Element elem) { 
     DOM.setStyleAttribute(elem, "overflow", "hidden"); 
    } 

    /** 
    * Adds as-needed scrolling to an element. 
    * 
    * @param elem 
    *   the element 
    */ 
    static final void addScrolling(final Element elem) { 
     DOM.setStyleAttribute(elem, "overflow", "auto"); 
    } 

    /** 
    * Sizes and element to consume the full area of its parent using the CSS 
    * properties left, right, top, and bottom. This method is used for all 
    * browsers except IE6/7. 
    * 
    * @param elem 
    *   the element 
    */ 
    static final void expandToFitParentUsingCssOffsets(final Element elem) { 
     final String zeroSize = "0px"; 
     ResizePanel.addAbsolutePositoning(elem); 
     ResizePanel.setLeft(elem, zeroSize); 
     ResizePanel.setRight(elem, zeroSize); 
     ResizePanel.setTop(elem, zeroSize); 
     ResizePanel.setBottom(elem, zeroSize); 
    } 

    /** 
    * Sizes an element to consume the full areas of its parent using 100% width 
    * and height. This method is used on IE6/7 where CSS offsets don't work 
    * reliably. 
    * 
    * @param elem 
    *   the element 
    */ 
    static final void expandToFitParentUsingPercentages(final Element elem) { 
     final String zeroSize = "0px"; 
     final String fullSize = "100%"; 
     ResizePanel.addAbsolutePositoning(elem); 
     ResizePanel.setTop(elem, zeroSize); 
     ResizePanel.setLeft(elem, zeroSize); 
     ResizePanel.setWidth(elem, fullSize); 
     ResizePanel.setHeight(elem, fullSize); 
    } 

    /* **************************************** */ 
    // Public Methods 
    /* **************************************** */ 
    /** {@inheritDoc} */ 
    @Override 
    public void add(final Widget widget) { 
     boolean canAddWidget = false; 
     for (int index = 0; index < this.widgets.length; index++) { 
      if (this.getWidget(index) == null) { 
       this.setWidget(index, widget); 
       canAddWidget = true; 
       break; 
      } 
     } 

     if (!canAddWidget) { 
      throw new IllegalStateException(
        "A Resizable panel can only contain two Widgets."); 
     } 
    } 

    /** {@inheritDoc} */ 
    public HandlerRegistration addResizeHandler(final ResizeEventHandler handler) { 
     return this.resizeHandlerManager.addHandler(ResizeEvent.TYPE, handler); 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Iterator<Widget> iterator() { 
     return ResizableControlIterator 
       .createWidgetIterator(this, this.widgets); 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public void onBrowserEvent(final Event event) { 
     switch (DOM.eventGetType(event)) { 
     case Event.ONMOUSEDOWN: 
      final Element target = DOM.eventGetTarget(event); 
      if (DOM.isOrHasChild(this.splitElem, target)) { 
       this.startResizingFrom(DOM.eventGetClientX(event) - this.getAbsoluteLeft(),DOM.eventGetClientY(event) - this.getAbsoluteTop()); 
       DOM.setCapture(this.getElement()); 
       DOM.eventPreventDefault(event); 
      } 
      break; 
     case Event.ONMOUSEUP: 
      if (this.isResizing()) { 
       // The order of these two lines is important. If we release 
       // capture 
       // first, then we might trigger an onLoseCapture event 
       // before we set 
       // isResizing to false. 
       DOM.releaseCapture(this.getElement()); 
       this.splitPositionSetDone(); 
       if (this.isResizing()) { 
        this.stopResizing(); 
       } 
      } 
      break; 
     case Event.ONMOUSEMOVE: 
      if (this.isResizing()) { 
       assert DOM.getCaptureElement() != null; 
       this.onSplitterResize(DOM.eventGetClientX(event) - this.getAbsoluteLeft(),DOM.eventGetClientY(event) - this.getAbsoluteTop()); 
       DOM.eventPreventDefault(event); 
      } 
      break; 
     // IE automatically releases capture if the user switches 
     // windows, so we 
     // need to catch the event and stop resizing. 
     case Event.ONLOSECAPTURE: 
      if (this.isResizing()) { 
       this.stopResizing(); 
      } 
      break;  
     case Event.ONTOUCHSTART: 
      final Element touchableTarget = DOM.eventGetTarget(event);   
      if (DOM.isOrHasChild(this.splitElem, touchableTarget)) { 
       this.startResizingFrom((event.getTouches().get(0).getClientX() - this.getAbsoluteLeft()),(event.getTouches().get(0).getClientY() - this.getAbsoluteTop())); 
       DOM.setCapture(this.getElement()); 
       event.preventDefault(); 
      } 
      break; 
     case Event.ONTOUCHMOVE: 
      if (this.isResizing()) { 
       assert DOM.getCaptureElement() != null; 
       this.onSplitterResize((event.getTouches().get(0).getClientX() - this.getAbsoluteLeft()),(event.getTouches().get(0).getClientY() - this.getAbsoluteTop())); 
       event.preventDefault(); 
      } 
      break; 
     // IE automatically releases capture if the user switches 
     // windows, so we 
     // need to catch the event and stop resizing. 
     case Event.ONTOUCHEND: 
      if (this.isResizing()) { 
       // The order of these two lines is important. If we release 
       // capture 
       // first, then we might trigger an onLoseCapture event 
       // before we set 
       // isResizing to false. 
       DOM.releaseCapture(this.getElement()); 
       this.splitPositionSetDone(); 
       if (this.isResizing()) { 
        this.stopResizing(); 
       } 
      } 
      break; 
     case Event.ONTOUCHCANCEL: 
      if (this.isResizing()) { 
       this.stopResizing(); 
      } 
      break; 
     default: 
      break; 
     } 
     super.onBrowserEvent(event); 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public boolean remove(final Widget widget) { 
     if (widget != null) { 
      for (int index = 0; index < this.widgets.length; index++) { 
       if ((this.widgets[index] == widget)) { 
        this.setWidget(index, null); 
        return true; 
       } 
      } 
     } 
     return false; 
    } 

    /** 
    * Moves the position of the splitter. 
    * 
    * @param size 
    *   the new size of the left region in CSS units (e.g. "10px", 
    *   "1em") 
    */ 
    public abstract void setSplitPosition(String size); 

    /** 
    * Split position set done. 
    * 
    */ 
    public abstract void splitPositionSetDone(); 

    /** 
    * Called on each mouse drag event as the user is dragging the splitter. 
    * 
    * @param x 
    *   the x coordinate of the mouse relative to the panel's extent 
    * @param y 
    *   the y coordinate of the mouse relative to the panel's extent 
    */ 
    abstract void onSplitterResize(int x, int y); 

    /** 
    * Called when the user starts dragging the splitter. 
    * 
    * @param x 
    *   the x coordinate of the mouse relative to the panel's extent 
    * @param y 
    *   the y coordinate of the mouse relative to the panel's extent 
    */ 
    abstract void onSplitterResizeStarted(int x, int y); 

    /* **************************************** */ 
    // Protected Methods 
    /* **************************************** */ 
    /** 
    * Gets the content element for the given index. 
    * 
    * @param index 
    *   the index of the element, only 0 and 1 are valid. 
    * @return the element 
    */ 
    protected Element getElement(final int index) { 
     return this.elements[index]; 
    } 

    /** 
    * Gets one of the contained widgets. 
    * 
    * @param index 
    *   the index of the widget, only 0 and 1 are valid. 
    * @return the widget 
    */ 
    protected Widget getWidget(final int index) { 
     return this.widgets[index]; 
    } 

    /** 
    * <b>Affected Elements:</b> 
    * <ul> 
    * <li>-splitter = the container containing the splitter element.</li> 
    * </ul> 
    * 
    * @param baseId 
    *   The base id. 
    * @see UIObject#onEnsureDebugId(String) 
    */ 
    @Override 
    protected void onEnsureDebugId(final String baseId) { 
     super.onEnsureDebugId(baseId); 
     UIObject.ensureDebugId(this.splitElem, baseId, "splitter"); 
    } 

    /** 
    * Sets one of the contained widgets. 
    * 
    * @param index 
    *   the index, only 0 and 1 are valid 
    * @param widget 
    *   the widget 
    */ 
    protected final void setWidget(final int index, final Widget widget) { 
     final Widget oldWidget = this.widgets[index]; 
     // Validate. 
     if (oldWidget == widget) { 
      return; 
     } 
     // Detach the new child. 
     if (widget != null) { 
      widget.removeFromParent(); 
     } 
     // Remove the old child. 
     if (oldWidget != null) { 
      // Orphan old. 
      try { 
       this.orphan(oldWidget); 
      } finally { 
       // Physical detach old. 
       DOM.removeChild(this.elements[0], oldWidget.getElement()); 
       this.widgets[index] = null; 
      } 
     } 
     // Logical attach new. 
     this.widgets[index] = widget; 
     if (widget != null) { 
      // Physical attach new. 
      DOM.appendChild(this.elements[0], widget.getElement()); 
      // Adopt new. 
      this.adopt(widget); 
     } 
    } 

    /* **************************************** */ 
    // Private Methods 
    /* **************************************** */ 
    /** 
    * Start resizing from. 
    * 
    * @param x 
    *   the x coordinate of the mouse relative to the panel's extent 
    * @param y 
    *   the y coordinate of the mouse relative to the panel's extent 
    */ 
    public void startResizingFrom(final int x, final int y) { 
     this.isResizing = true; 
     this.onSplitterResizeStarted(x, y); 
     // Resize glassElem to take up the entire scrollable window area 
     final int height = RootPanel.getBodyElement().getScrollHeight() - 1; 
     final int width = RootPanel.getBodyElement().getScrollWidth() - 1; 
     ResizePanel.glassElem.getStyle().setProperty("height", height + "px"); 
     ResizePanel.glassElem.getStyle().setProperty("width", width + "px"); 
     RootPanel.getBodyElement().appendChild(ResizePanel.glassElem); 
    } 

    /** 
    * Stop resizing. 
    */ 
    void stopResizing() { 
     this.isResizing = false; 
     // FIXME:: Why is the remove causing error. 
     try { 
      RootPanel.getBodyElement().removeChild(ResizePanel.glassElem); 
     } catch (final Exception e) { 
      GWT.log("Got error removing the glassElem: " + e); 
     } 
    } 
} 

還添加我的事件和事件處理程序

ResizeEvent.java

/** 
* When panels (Ex: VerticalSplitPanel) are resized, adjust the positions. 
*/ 
public class ResizeEvent extends GwtEvent<ResizeEventHandler> { 

    /* **************************************** */ 
    // Public Static Fields 
    /* **************************************** */ 
    /** The Constant TYPE. */ 
    public static final Type<ResizeEventHandler> TYPE = new Type<ResizeEventHandler>(); 

    /* **************************************** */ 
    // Private Fields 
    /* **************************************** */ 
    /** The split size. */ 
    private final int splitSize; 

    /* **************************************** */ 
    // Constructors 
    /* **************************************** */ 
    /** 
    * Instantiates a new view set event. 
    * 
    * @param splitSize 
    *   The split size. 
    */ 
    public ResizeEvent(final int splitSize) { 
     this.splitSize = splitSize; 
    } 

    /* **************************************** */ 
    // Public Properties 
    /* **************************************** */ 
    /** {@inheritDoc} */ 
    @Override 
    public Type<ResizeEventHandler> getAssociatedType() { 
     return ResizeEvent.TYPE; 
    } 

    /** 
    * Gets the top position. 
    * 
    * @return The split position. 
    */ 
    public int getSplitSize() { 
     return splitSize; 
    } 

    /* **************************************** */ 
    // Protected Methods 
    /* **************************************** */ 
    /** {@inheritDoc} */ 
    @Override 
    protected void dispatch(final ResizeEventHandler handler) { 
     handler.onResize(this); 
    } 

} 

ResizeEventHandler.java

/** 
* The Interface ResizeEventHandler. 
*/ 
public interface ResizeEventHandler extends EventHandler { 

    /** 
    * On move. 
    * 
    * @param event 
    *   The event. 
    */ 
    void onResize(ResizeEvent event); 
}