Actionscript 3 “我怎么能?”;不可接受;拖拉式弹性体?

Actionscript 3 “我怎么能?”;不可接受;拖拉式弹性体?,actionscript-3,apache-flex,drag-and-drop,Actionscript 3,Apache Flex,Drag And Drop,一旦我调用了DragManager.acceptDrag是否有办法“取消接受”拖动?假设我有一个可以接受拖放的视图,但只能在某些区域。一旦用户拖动到其中一个区域上,我就调用DragManager.acceptDrag(this)(从DragEvent.DRAG\u拖过处理程序),但是如果用户随后移出该区域,我想将拖动的状态更改为notaccepted,并显示DragManager.NONE反馈。但是,调用DragManager.acceptDrag(null)或DragManager.showF

一旦我调用了
DragManager.acceptDrag
是否有办法“取消接受”拖动?假设我有一个可以接受拖放的视图,但只能在某些区域。一旦用户拖动到其中一个区域上,我就调用
DragManager.acceptDrag(this)
(从
DragEvent.DRAG\u拖过
处理程序),但是如果用户随后移出该区域,我想将拖动的状态更改为notaccepted,并显示
DragManager.NONE
反馈。但是,调用
DragManager.acceptDrag(null)
DragManager.showFeedback(DragManager.NONE)
似乎都没有任何效果。一旦我接受了拖拽并设置了反馈类型,我似乎无法改变它

要明确的是:用户应该能够放置的区域不是组件,甚至不是显示对象,事实上它们只是文本字段文本中的范围(如选择)。如果它们是自己的组件,我可以通过让它们各自接受拖动事件来解决它。我想我可以创建浮动在文本上的代理组件来模拟它,但如果没有必要,我宁愿不创建


我已经设法让它在AIR和浏览器中都能工作了,但只有通过将代理组件放在文本范围的顶部,这样你才能放下东西。这样我就得到了正确的反馈,并且在拖动退出时自动不接受拖放

这是D&D在空中最奇怪的事情:

DragManager.doDrag(initiator, source, event, dragImage, offsetX, offsetY);
在基于浏览器的Flex中,
offsetX
offsetY
应该是负数(文档中这么说,它可以正常工作)。但是,在空中运行完全相同的代码时,必须使偏移量为正值。相同的数字,但为正。这是非常非常奇怪的


我已经做了更多的测试,测试什么有效,但如果你在空气中跑步就不行了。看起来空气中的阻力和下降是不同的。这真的很奇怪,因为不仅反馈没有正确显示,而且不可能不被接受,而且坐标也完全不正确。我只是在浏览器中而不是在空中尝试了我的应用程序,拖放操作完全失败了


此外,跳过dragEnter处理程序在空气中也可以正常工作,但在浏览器中运行时会破坏一切。

是否仅使用dragEnter方法?如果您试图拒绝拖动,但仍在同一组件上拖动,则需要同时使用dragEnter和dragOver方法

看看这个例子:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
        <![CDATA[
            import mx.core.DragSource;
            import mx.managers.DragManager;
            import mx.events.DragEvent;

            private function onDragEnter(e:DragEvent):void {
                if ( e.target == lbl ) {

                    if ( e.localX < lbl.width/2 ) {
                        trace("accept");
                        DragManager.acceptDragDrop(this);
                    }
                    else {
                        DragManager.acceptDragDrop(null);
                    }
                }
            }

            private function doStartDrag(e:MouseEvent):void {
                if ( e.buttonDown ) {
                    var ds:DragSource = new DragSource();
                    ds.addData("test", "text");

                    DragManager.doDrag(btn, ds, e);
                }
            }
        ]]>
    </mx:Script>
    <mx:Label id="lbl" text="hello world!" left="10" top="10" dragEnter="onDragEnter(event)" dragOver="onDragEnter(event)" />
    <mx:Button id="btn" x="47" y="255" label="Button" mouseMove="doStartDrag(event)"/>
</mx:Application>

好的,我现在看到问题了。请尝试将其设置为绘图初始化器,而不是null

看看这个

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.DragEvent;
            import mx.managers.DragManager;
            import mx.core.DragSource;

            private function doStartDrag(e:MouseEvent):void {
                if ( e.buttonDown && !DragManager.isDragging ) {
                var ds:DragSource = new DragSource();
                ds.addData("test", "test");

                DragManager.doDrag(btn, ds, e);
                }
            }

            private function handleDragOver(e:DragEvent):void {
                if ( e.localX < cvs.width/2 ) {
                    //since null does nothing, lets just set to accept the drag
                    //operation, but accept it to the dragInitiator
                    DragManager.acceptDragDrop(e.dragInitiator);
                }   
                else {
                    //accept drag
                    DragManager.acceptDragDrop(cvs);
                    DragManager.showFeedback( DragManager.COPY );
                }
            }

            private function handleDragDrop(e:DragEvent):void {
                if ( e.dragSource.hasFormat("test") ) {
                    Alert.show("Got a drag drop!");
                }
            }
        ]]>
    </mx:Script>
    <mx:Canvas x="265" y="66" width="321" height="245" backgroundColor="#FF0000" id="cvs" dragOver="handleDragOver(event)" dragDrop="handleDragDrop(event)">
    </mx:Canvas>
    <mx:Button id="btn" x="82" y="140" label="Drag Me" mouseDown="doStartDrag(event)"/>
</mx:WindowedApplication>

是的,拖放在空中是不同的。我讨厌那样!要想弄清楚如何使事情与flex中内置的定制dnd一样工作,需要进行大量的研究

至于坐标,可以使用localToContent和localToGlobal方法。它们可能有助于将坐标转换成有用的东西


祝你好运。如果我想到其他任何事情,我会告诉您。

如果您不需要在空中进行本机拖放,您可以通过子类化WindowedApplication并设置DragManager来获得Flex拖放行为。有关更多信息,请参阅Adobe Jira上的这篇文章:

您误解了这个概念。您的“不接受”是通过实现dragOverHandler并发出不需要数据的信号来实现的

以下是基本概念:

  • 注册dragEnterHandler或重写已注册的方法

    function dragEnterHandler(event: DragEvent):void {
        if (data suites at least one location in this component)
            DragManager.acceptDragDrop(this);
    }
    
    function dragOverHandler(event: DragEvent):void {
        if (data suites at least no location in this component) {
            DragManager.showFeedback(DragManager.NONE);
            return;
        }
    
        ... // handle other cases and show the cursor / icon you want
    }
    
    function dragOverHandler(event: DragEvent):void {
        // handle the recieved data as you like.
    }
    
    这使您的容器能够接收更多消息(dragOver/dragExit)。但这不是决定应该显示哪种鼠标光标的位置

    DragManager.acceptDragDrop(此)不调用其他处理程序

  • 注册dragOverHandler或重写已注册的方法

    function dragEnterHandler(event: DragEvent):void {
        if (data suites at least one location in this component)
            DragManager.acceptDragDrop(this);
    }
    
    function dragOverHandler(event: DragEvent):void {
        if (data suites at least no location in this component) {
            DragManager.showFeedback(DragManager.NONE);
            return;
        }
    
        ... // handle other cases and show the cursor / icon you want
    }
    
    function dragOverHandler(event: DragEvent):void {
        // handle the recieved data as you like.
    }
    
    调用DragManager.showFeedback(DragManager.NONE)执行显示“未接受”的技巧

  • 注册dragExitHandler或重写已注册的方法

    function dragEnterHandler(event: DragEvent):void {
        if (data suites at least one location in this component)
            DragManager.acceptDragDrop(this);
    }
    
    function dragOverHandler(event: DragEvent):void {
        if (data suites at least no location in this component) {
            DragManager.showFeedback(DragManager.NONE);
            return;
        }
    
        ... // handle other cases and show the cursor / icon you want
    }
    
    function dragOverHandler(event: DragEvent):void {
        // handle the recieved data as you like.
    }
    

  • drag\u ENTER
    处理程序中接受拖动只会让事情变得更糟。我仍然无法拒绝拖动(调用
    DragManager.acceptDragDrop(null)
    没有效果,至少没有可见效果),并且在回车时接受拖动会删除我的小控件。现在,鼠标一进入组件,指针下方的+就会显示出来,而不是在用户拖动特定区域时开始显示。这也会使启动器成为目标,在用户拖动该组件时显示+(因为它不接受拖放,所以绝对不应该显示)。所以这也不起作用。