我怎样才能“不接受”Flex中的拖累?

时间:2008-08-14 10:32:53

标签: actionscript-3 flex drag-and-drop

一旦我打电话给DragManager.acceptDrag,有没有办法“不接受”拖累?假设我有一个可以接受拖放的视图,但仅限于某些区域。一旦用户拖动其中一个区域,我就会调用DragManager.acceptDrag(this)(来自DragEvent.DRAG_OVER处理程序),但如果用户移出此区域,我想将拖动的状态更改为接受并显示DragManager.NONE反馈。但是,调用DragManager.acceptDrag(null)DragManager.showFeedback(DragManager.NONE)似乎都没有任何效果。一旦我接受了拖动设置反馈类型,我似乎无法改变它。

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


我已经设法让它现在在AIR和浏览器中工作,但只能将代理组件置于文本范围之上,你应该能够放弃它。这样我就可以得到正确的反馈,并且在拖动出口处自动取消接收。

这是关于AIR中D& D最奇怪的事情:

DragManager.doDrag(initiator, source, event, dragImage, offsetX, offsetY);

在基于浏览器的Flex中,offsetXoffsetY应该是否定的(所以文档说,它可以正常工作)。但是,在AIR中运行完全相同的代码时,必须使偏移量为正。相同的数字,但积极的。这非常非常奇怪。


我已经测试了更多以及@maclema的工作原理,但是如果你在AIR中运行则不行。看起来AIR中的拖放是不同的。这真的非常奇怪,因为不仅反馈没有正确显示,也不可能不接受,但坐标也完全关闭。我只是在浏览器而不是AIR中尝试了我的应用程序,并且完全打破了拖放操作。

此外,跳过dragEnter处理程序在AIR中运行正常,但在浏览器中运行时会破坏所有内容。

5 个答案:

答案 0 :(得分:6)

您是否只使用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>

答案 1 :(得分:1)

如果您不需要在AIR中进行本机拖放,则可以通过继承WindowedApplication并设置DragManager来获得Flex拖放行为。有关详情,请参阅Adobe Jira上的这篇文章:https://bugs.adobe.com/jira/browse/SDK-13983

答案 2 :(得分:1)

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

这是基本概念:

  1. 注册dragEnterHandler或覆盖已注册的方法。

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

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

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

  2. 注册dragOverHandler或覆盖已注册的方法。

    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); 可以显示“unaccept”。

  3. 注册dragExitHandler或覆盖已注册的方法。

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

答案 3 :(得分:0)

好吧,我现在看到了问题。而不是null,尝试将其设置为dragInitiator。

检查一下。

<?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>

答案 4 :(得分:0)

是的,AIR中的拖放是不同的。我讨厌那个!需要花很多时间来解决如何使用与flex内置的自定义dnd相同的工作方式。

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

祝你好运。如果我想到别的什么,我会通知你。