如何"不接受" Flex中的拖动?
一旦我叫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中," offsetX"和" offsetY"应该为负(因此,文档说,它可以正常工作)。但是,在AIR中运行完全相同的代码时,必须使偏移量为正。相同的数字,但为正数。那是非常非常奇怪的。
我已经测试了更多内容以及@maclema的工作原理,但是如果我们在AIR中运行,则不会进行测试。似乎AIR中的拖放操作有所不同。这真的很奇怪,因为不仅反馈无法正确显示,而且无法接受,而且坐标也完全不正确。我只是在浏览器而不是AIR中尝试了我的应用程序,并且拖放操作完全中断了。
另外,跳过dragEnter处理程序在AIR中效果很好,但是在浏览器中运行时会中断所有操作。
解决方案
回答
我们仅使用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>
回答
好的,我现在看到了问题。尝试将其设置为dragInitiator而不是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>
回答
是的,拖放在AIR中有所不同。我讨厌那个!需要花很多时间才能弄清楚如何使事情与flex中内置的自定义dnd相同。
至于坐标,也许可以使用localToContent和localToGlobal方法。它们可能有助于将坐标转换为有用的东西。
祝你好运。如果我有其他想法,我会让我们知道。
回答
如果不需要AIR中的本机拖放,则可以通过子类化WindowedApplication并设置DragManager来获得Flex拖放行为。有关更多信息,请参阅Adobe Jira上的这篇文章:https://bugs.adobe.com/jira/browse/SDK-13983