Как я могу «отменить» перетаскивание в Flex?

После того, как я позвонил в 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, но при запуске в браузере все прерывается.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
5 100
5

Ответы 5

Вы используете только метод 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>

Принятие сопротивления в обработчике DRAG_ENTER только усугубляет ситуацию. Я все еще не могу отклонить перетаскивание (вызов DragManager.acceptDragDrop(null) не имеет никакого эффекта, по крайней мере, не имеет видимого эффекта), а принятие перетаскивания при вводе удаляет небольшой контроль, который у меня был. Теперь значок + под указателем отображается, как только мышь входит в компонент, вместо того, чтобы показывать, когда пользователь перетаскивает специальные области.

Theo 14.08.2008 20:26

ну, это также сделало бы инициатор целью, показывая +, когда пользователь перетаскивает этот компонент (чего определенно не должно быть, поскольку он не принимает отбрасывания). Так что это тоже не работает.

Theo 16.08.2008 13:26

хорошо, теперь я вижу проблему. Вместо 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 и сигнализации о том, что данные не нужны.

Вот основная концепция:

  1. зарегистрируйте dragEnterHandler или переопределите уже зарегистрированный метод.

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

    Это позволяет вашему контейнеру получать дальнейшие сообщения (dragOver / dragExit). Но это НЕТ - место, чтобы решить, какой вид курсора мыши должен отображаться.

    Без DragManager.acceptDragDrop (это); другие обработчики не вызываются.

  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); позволяет отобразить «непринятие».

  3. зарегистрируйте dragExitHandler или переопределите уже зарегистрированный метод.

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

Другие вопросы по теме