После того, как я позвонил в DragManager.acceptDrag, есть ли способ «отменить» перетаскивание? Скажем, у меня есть представление, которое поддерживает перетаскивание, но только в определенных областях. Как только пользователь перетаскивает одну из этих областей, я вызываю DragManager.acceptDrag(this) (из обработчика DragEvent.DRAG_OVER), но если пользователь затем покидает эту область, я хотел бы изменить статус перетаскивания на «Не принято» и показать обратную связь DragManager.NONE. Однако ни вызов DragManager.acceptDrag(null), ни DragManager.showFeedback(DragManager.NONE), похоже, не имеют никакого эффекта. Как только я принял перетаскивание и установил тип обратной связи, я не могу его изменить.
Чтобы было ясно: области, которые пользователь должен иметь возможность отбрасывать, не являются компонентами или даже отображаемыми объектами, на самом деле это просто диапазоны в тексте текстового поля (например, выделение). Если бы они были собственными компонентами, я мог бы решить эту проблему, заставив каждый из них принимать события перетаскивания индивидуально. Думаю, я мог бы создать прокси-компоненты, которые плавают над текстом, чтобы имитировать его, но я бы предпочел не делать этого, если в этом нет необходимости.
Мне удалось заставить его работать как в AIR, так и в браузере, но только путем помещения прокси-компонентов поверх тех диапазонов текста, в которые вы должны иметь возможность отбрасывать вещи. Таким образом, я получаю правильную обратную связь, и при выходе перетаскивания капли автоматически не принимаются.
Это самая странная особенность D&D в AIR:
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>
ну, это также сделало бы инициатор целью, показывая +, когда пользователь перетаскивает этот компонент (чего определенно не должно быть, поскольку он не принимает отбрасывания). Так что это тоже не работает.
хорошо, теперь я вижу проблему. Вместо 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>
Да, перетаскивание в AIR отличается. Я ненавижу это! Чтобы понять, как заставить что-то работать так же, как настраиваемый dnd, встроенный в flex, требуется много времени.
Что касается координат, может быть, поиграйте с методами localToContent и localToGlobal. Они могут помочь в переводе координат во что-нибудь полезное.
Удачи. Я дам вам знать, если придумаю что-нибудь еще.
Если вам не требуется собственное перетаскивание в AIR, вы можете получить поведение перетаскивания Flex, создав подкласс WindowedApplication и установив DragManager. См. Этот пост в Adobe Jira для получения дополнительной информации: https://bugs.adobe.com/jira/browse/SDK-13983
Вы неправильно понимаете концепцию. Ваше «непринятие» достигается за счет реализации dragOverHandler и сигнализации о том, что данные не нужны.
Вот основная концепция:
зарегистрируйте dragEnterHandler или переопределите уже зарегистрированный метод.
function dragEnterHandler(event: DragEvent):void {
if (data suites at least one location in this component)
DragManager.acceptDragDrop(this);
}
Это позволяет вашему контейнеру получать дальнейшие сообщения (dragOver / dragExit). Но это НЕТ - место, чтобы решить, какой вид курсора мыши должен отображаться.
Без DragManager.acceptDragDrop (это); другие обработчики не вызываются.
зарегистрируйте 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); позволяет отобразить «непринятие».
зарегистрируйте dragExitHandler или переопределите уже зарегистрированный метод.
function dragOverHandler(event: DragEvent):void {
// handle the recieved data as you like.
}
Принятие сопротивления в обработчике
DRAG_ENTERтолько усугубляет ситуацию. Я все еще не могу отклонить перетаскивание (вызовDragManager.acceptDragDrop(null)не имеет никакого эффекта, по крайней мере, не имеет видимого эффекта), а принятие перетаскивания при вводе удаляет небольшой контроль, который у меня был. Теперь значок + под указателем отображается, как только мышь входит в компонент, вместо того, чтобы показывать, когда пользователь перетаскивает специальные области.