После того, как я позвонил 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>
хорошо, я вижу проблему сейчас. Вместо нуля, попробуйте установить его в 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); делает трюк для отображения "unaccept".
зарегистрируйте dragExitHandler или переопределите уже зарегистрированный метод.
function dragOverHandler(event: DragEvent):void { // handle the recieved data as you like. }
DRAG_ENTER
обработчике только ухудшает ситуацию. Я все еще не могу отклонить перетаскивание (вызов неDragManager.acceptDragDrop(null)
имеет никакого эффекта, по крайней мере, никакого видимого эффекта), и принятие перетаскивания на ввод удаляет тот небольшой контроль, который у меня был. Теперь указатель + под указателем отображается, как только мышь входит в компонент, а не начинает показывать, когда пользователь перетаскивает специальные области.