关于 actionscript 3:如何在 Flex 中”不接受”拖动?

关于 actionscript 3:如何在 Flex 中”不接受”拖动?

How can I "unaccept" a drag in Flex?

一旦我调用了DragManager.acceptDrag,有什么办法可以"不接受"拖拽吗?假设我有一个可以接受拖放的视图,但仅限于某些区域。一旦用户拖过这些区域之一,我就会调用 DragManager.acceptDrag(this) (来自 DragEvent.DRAG_OVER 处理程序),但是如果用户随后移出该区域,我想将拖动的状态更改为不接受并显示DragManager.NONE 反馈。但是,调用 DragManager.acceptDrag(null)DragManager.showFeedback(DragManager.NONE) 似乎都没有任何效果。一旦我接受了拖动设置反馈类型,我似乎无法更改它。

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

我现在已经设法让它在 AIR 和浏览器中运行,但只能通过将代理组件放在应该能够放置内容的文本范围的顶部。这样我就可以得到正确的反馈,并且在拖动退出时会自动不接受放置。

这是D最奇怪的地方


您是否只使用了dragEnter 方法?如果您尝试拒绝拖动,同时仍拖动同一组件,则需要同时使用 dragEnter 和 dragOver 方法。

看看这个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
?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

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

这是基本概念:

  • 注册dragEnterHandler或者覆盖已经注册的方法。

    1
    2
    3
    4
    function dragEnterHandler(event: DragEvent):void {
        if (data suites at least one location in this component)
            DragManager.acceptDragDrop(this);
    }

    这使您的容器能够接收更多消息(dragOver/dragExit)。但这不是决定应该显示哪种鼠标光标的位置。

    没有 DragManager.acceptDragDrop(this);不会调用其他处理程序。

  • 注册dragOverHandler或者覆盖已经注册的方法。

    1
    2
    3
    4
    5
    6
    7
    8
    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
    }

    调用 DragManager.showFeedback(DragManager.NONE);显示"不接受"的诀窍。

  • 注册dragExitHandler或者覆盖已经注册的方法。

    1
    2
    3
    function dragOverHandler(event: DragEvent):void {
        // handle the recieved data as you like.
    }

  • 如果您不需要在 AIR 中进行原生拖放,则可以通过子类化 WindowedApplication 并设置 DragManager 来获得 Flex 拖放行为。有关更多信息,请参阅 Adob??e Jira 上的此帖子:https://bugs.adobe.com/jira/browse/SDK-13983


    是的,拖放在 AIR 中是不同的。我讨厌那个!要想弄清楚如何让事情像在 flex 中构建的自定义 dnd 一样工作,需要花费很多时间。

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

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


    好的,我现在看到了问题。尝试将其设置为 dragInitiator.

    而不是 null

    看看这个。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    ?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


    推荐阅读