【问题标题】:How to prevent a component from being dragged out of the stage in Flex 3Flex 3中如何防止组件被拖出舞台
【发布时间】:2010-12-07 10:31:45
【问题描述】:

我认为这个问题有一个简单的解决方案,只是不够简单,我找不到。

问题: 你如何限制 Flex 3 中的 TitleWindow 被拖出屏幕/舞台?有没有办法将 TitleWindow 限制在查看区域?

示例:假设我有一个占据 100% 屏幕的应用程序。接下来,我通过 PopUpManager 创建一个 TitleWindow。然后我可以继续单击并按住(拖动)该窗口离开屏幕,然后释放鼠标按钮。该窗口现在在屏幕外某处丢失。有没有办法防止窗口被拖出查看区域?

提前感谢您的帮助。

【问题讨论】:

    标签: apache-flex


    【解决方案1】:

    您可以将其isPopUp 属性设置为false 以防止它被拖动。

    var popupWin:TitleWindow = PopUpManager.createPopUp(this, TitleWindow);
    PopUpManager.centerPopUp(popupWin);
    popupWin.isPopUp = false;
    

    我不知道flex中的DragManager类是否支持边界检查,但是如果你真的想允许拖动但限制它的边界,你仍然可以将isPopUp设置为false并自己实现拖动代码,这样该组件永远不会超出您指定的限制。以startDrag() 方法为例。边界矩形是关键。

    【讨论】:

    • 感谢您的回复。是的,我可以将 isPop 属性设置为 false。但是,如果可能的话,我仍然希望窗口可以拖动。好建议。谢谢。如果没有解决方案,我可能不得不走这条路。
    • 他们的示例将 mouseUp 事件添加到拖动的对象 - 您可能希望将其更改为 stage 以便即使用户在标题窗口之外释放鼠标也会触发它。
    • 重写 TitleWindow 类以访问其受保护的 titleBar 属性。给titleBar添加mouseDown事件,在mouseDownHandler中,调用titlewindow.startDrag,给stage添加mouseUp监听。从 mouseUpHandler 调用 stopDrag。
    • 我希望我在某处俯瞰某个对象的属性。但是您提供的解决方案很有希望。经过一番工作,我采用了您的原始解决方案; isPopUp = 假。感谢您的帮助。
    【解决方案2】:

    继承 TitleWindow 并在标题栏上添加一个画布作为拖动代理。然后你可以显式调用带有边界矩形的 startDrag。

    这很简陋,但应该会让你走上正轨……

    使用代理的原因是,如果您没有画布覆盖它,则单击 titleBar 标签时可能会出现一些奇怪的行为。

    public class MyTitleWindow extends TitleWindow
    {
        public var titleBarOverlay:Canvas;
    
        override protected function createChildren():void
        {
            super.createChildren();
    
            if(!titleBarOverlay)
            {
                titleBarOverlay = new Canvas();
                titleBarOverlay.width = this.width;
                titleBarOverlay.height = this.titleBar.height;
                titleBarOverlay.alpha = 0;
                titleBarOverlay.setStyle("backgroundColor", 0x000000);
                rawChildren.addChild(titleBarOverlay);
            }
    
                addListeners();
        }
    
        override protected function updateDisplayList(w:Number, h:Number):void
        {
            super.updateDisplayList(w, h);
    
            titleBarOverlay.width = this.width;
            titleBarOverlay.height = this.titleBar.height;
        }
    
        private function addListeners():void
        {
            titleBarOverlay.addEventListener(MouseEvent.MOUSE_DOWN, onTitleBarPress, false, 0, true);
            titleBarOverlay.addEventListener(MouseEvent.MOUSE_UP, onTitleBarRelease, false, 0, true);
        }
    
        private function onTitleBarPress(event:MouseEvent):void
        {
            // Here you can set the boundary using owner, parent, parentApplication, etc.
            this.startDrag(false, new Rectangle(0, 0, parent.width - this.width, parent.height - this.height));
        }
    
        private function onTitleBarRelease(event:Event):void
        {
            this.stopDrag();
        }
    }
    

    【讨论】:

    • 叠加层需要什么?为什么不直接给titleBar添加事件监听呢?
    • 感谢丹尼尔的反馈,感谢您为回复所付出的努力和时间。
    【解决方案3】:

    这是一个非常古老的帖子,但这里有另一种方法: 无论您是否扩展组件,在 TitleWindow 定义中添加以下行:move:"doMove(event)" 导入应用程序库(import mx.core.Application;) 并添加 doMove 函数:

    private function doMove(event:Event):void
    {//keeps TW inside layout
        var appW:Number=Application.application.width;
        var appH:Number=Application.application.height;
        if(this.x+this.width>appW)
        {
            this.x=appW-this.width;
        }
        if(this.x<0)
        {
            this.x=0;
        }
        if(this.y+this.height>appH)
        {
            this.y=appH-this.height;
        }
        if(this.y<0)
        {
            this.y=0;
        }
    }
    

    【讨论】:

    • 赫克托!你做到了!你就是那个男人!这正是我一直在寻找的。谢谢。
    【解决方案4】:

    您可以简单地覆盖移动功能并防止“非法”移动(它由面板拖动管理内部调用)。

    我认为你也应该听听舞台大小调整,因为缩小它(例如,如果用户调整浏览器窗口的大小)即使没有实际移动它也会让你的弹出窗口离开舞台。

    public class MyTitleWindow extends TitleWindow {
    
        public function MyTitleWindow() {
            // use a weak listener, or remember to remove it
            stage.addEventListener(Event.RESIZE, onStageResize, 
                    false, EventPriority.DEFAULT, true);
        }
    
        private function onStageResize(event:Event):void {
            restoreOutOfStage();
        }
    
        override public function move(x:Number, y:Number):void {
            super.move(x, y);
            restoreOutOfStage();
        }
    
        private function restoreOutOfStage():void {
            // avoid the popup from being positioned completely out of stage
            // (use the actual width/height of the popup instead of 50 if you
            // want to keep your *entire* popup on stage)
            var topContainer:DisplayObjectContainer =
                    Application.application.parentDocument;
            var minX:int = 50 - width;
            var maxX:int = topContainer.width - 50;
            var minY:int = 0;
            var maxY:int = topContainer.height - 50;                
            if (x > maxX) 
                x = maxX
            else if (x < minX)
                x = minX;
            if (y > maxY) 
                y = maxY
            else if (y < minY)
                y = minY;
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      Flex 4

      <s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx"
            windowMoving="windowMovingHandler(event)">
      .
      .
      .
      
      protected function windowMovingHandler(event:TitleWindowBoundsEvent):void
      {
        var appBounds:Rectangle = parentApplication.getBounds(DisplayObject(parentApplication));
        if(!appBounds.containsRect(event.afterBounds)){
          event.preventDefault();
        }
      }
      
      // for better precision, corect appBounds manualy, or, instead of "parentApplication.getBounds..." create new rectangle of your application size
      

      【讨论】:

        【解决方案6】:
        【解决方案7】:

        在 TitleWindow 的 creationComplete 处理程序中添加以下内容:

        this.moveArea.visible=false;
        

        这样就可以了。

        另一方面,如果您有自定义皮肤,则可以删除“moveArea”部分。这也应该有效。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-11
          • 2020-04-12
          • 1970-01-01
          • 1970-01-01
          • 2012-08-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多