Accessibility

Flex Quick Starts: Building an advanced user interface

Table of contents


Adding drag-and-drop support

Visual development environments typically let you manipulate objects in an application by selecting them with a mouse and moving them around the screen. The Adobe® Flex™ Drag and Drop Manager lets you select an object, such as an item in a List control, or a Flex control, such as an Image control, and then drag it over another component to add it to that component. All Flex components support the drag-and-drop operation. Flex also includes additional support for the drag-and-drop operation for certain controls, such as List, Tree, and DataGrid.

The drag-and-drop operation has three main stages: initiation, dragging, and dropping.

Initiation

A user initiates a drag-and-drop operation by using the mouse to select a Flex component or an item in a Flex component, and then moving the component or item while holding down the mouse button. For example, a user selects an item in a List control with the mouse and, while holding down the mouse button, moves the mouse several pixels. The selected component is called the drag initiator.

Dragging

While holding down the mouse button, the user moves the mouse around the Flex application. Flex displays an image during the drag, which is the drag proxy. The drag source (a DragSource object) contains the data being dragged.

Dropping

When a user moves the drag proxy over another Flex component, that component becomes a possible drop target. The drop target can inspect the drag source to determine whether the data is in a format that the target accepts and, if so, let the user drop the data onto it. If the drop target determines that the data is not in an acceptable format, the drop target can disallow the drop operation.

Upon a successful drop operation, Flex adds the data to the target and, optionally, deletes it from its original location.

This Quick Start describes several ways of implementing the drag-and-drop operation in your Flex applications.

Using drag-and-drop with List controls

Several Flex controls include built-in support for the drag-and-drop operation. These are the DataGrid, HorizontalList, List, Menu, PrintDataGrid, TileList, and Tree controls.

You can make these controls drag initiators by setting the dragEnabled property to true. Similarly, you can make these controls drop targets by setting the dropEnabled property to true. Flex lets you move items by dragging them from a drag-enabled control to a drop-enabled control, or copy them by dragging while pressing the Control key.

Copying items by using the drag-and-drop operation

The following example lets you copy items from one List control to another by dragging them. You can copy the same item multiple times from the drag initiator to the drop target.

Example

<?xml version="1.0" encoding="utf-8"?>

<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    width="365" height="225" 
    creationComplete="creationCompleteHandler();"
>

    <mx:Script>
        <![CDATA[
                private function creationCompleteHandler():void 
                {

                    srclist.dataProvider = ['Reading', 'Skating', 'Movies'];        
                    destlist.dataProvider = [];
                }

        ]]>
    </mx:Script>

    <mx:Panel title="Select activities" layout="horizontal">
        <mx:VBox width="50%">

            <mx:Label text="Available activities"/>

            <!-- Drag initiator -->
            <mx:List 
                id="srclist" width="100%" height="100" 
                allowMultipleSelection="true"                
                dragEnabled="true"

            />

        </mx:VBox>

        <mx:VBox width="50%">
            <mx:Label text="Activities I enjoy"/>

            <!-- Drop target -->
            <mx:List  
                id="destlist" width="100%" height="100" 
                dropEnabled="true"

            />

        </mx:VBox>
    </mx:Panel>
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.


Moving items by using the drag-and drop operation

The default value of the dragMoveEnabled property is false, which only lets you copy items from one List control to the other. If you modify the previous example and add the dragMoveEnabled property set to true in the source List control, you can move and copy elements, as the following example shows.

The default action is to move the item. To copy an item, hold down the Control key during the drop operation.

Example

<!-- Drag initiator -->
<mx:List 
    id="srclist" width="100%" height="100" 
    allowMultipleSelection="true"                
    dragEnabled="true"

    dragMoveEnabled="true"
/>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.


Two-way drag-and drop support

You can allow two-way dragging and dropping by setting the dragEnabled property and the dropEnabled property to true on both List controls, as follows:

Example

<!-- Both drag initiator and drop target -->
<mx:List 
    id="srclist" width="100%" height="100" 
    allowMultipleSelection="true"                
    dragEnabled="true"

    dropEnabled="true"
    dragMoveEnabled="true"
/>

<!-- . . . -->

<!-- Both drag initiator and drop target -->
<mx:List  
    id="destlist" width="100%" height="100" 
    allowMultipleSelection="true"                
    dragEnabled="true"

    dropEnabled="true"
    dragMoveEnabled="true"
/>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Manually adding drag-and-drop support

To support drag-and-drop operations with non-list-based controls, or with containers, you must explicitly add support by using a series of special classes and events. You use the DragManager, DragSource, and DragEvent classes to implement the drag-and-drop operation.

Flex applications use events to control drag-and-drop operations.

Drag initiator events

When you set a control to act as a drag initiator, you can use the mouseDown, mouseMove, and dragComplete events to manage the drag-and-drop operation.

The mouseDown and mouseMove events

The mouseDown event is dispatched when a user selects a control with the mouse and holds down the mouse button. The mouseMove event is dispatched when the mouse moves.

The following example embeds the images of four Euro coins (1 cent, 2 cent, 5 cent, and 10 cent) and displays them using Image controls. In each of the Image controls, you listen for the mouseMove event and define an event handler method called dragIt() to handle this event. In the dragIt() method, you obtain a reference to the coin image that the event originated on by using the currentTarget property of the event object and save this reference in a local variable called dragInitiator.

Next, you create a DragSource instance and call its addData() method to store the value argument that was passed to the dragIt() method. You describe the format of the value argument by using the String "value". You use this string later, when creating your drop target, to check whether you should allow an item to be dropped on it.

Because you want to display an image of the coin as the user drags it around, you create an Image instance and set its source to the same coin image that the drag initiator has. You save this image in a local variable called dragProxy.

Finally, you call the static doDrag() method on the DragManager class and pass it references to the drag initiator, drag source, the event object, and the drag proxy to start the drag operation.

You can drag the coins around but you cannot drop them anywhere because you haven't defined a drop target. The following section describes how to define a drop target.

Example

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"     
    viewSourceURL="src/DragAndDropDragInitiatorEvents/index.html"

    width="500" height="160" 
>
    <mx:Script>
        <![CDATA[

            import mx.managers.DragManager;
            import mx.core.DragSource;
            
            // Embed the various Euro coin images. Images originally 
            // from Wikipedia (http://en.wikipedia.org/wiki/Euro_coins)
            [Embed("assets/1c.png")]

            []
            public var OneCent:Class;
            
            [Embed("assets/2c.png")]

            []
            public var TwoCents:Class;
            
            [Embed("assets/5c.png")]

            []
            public var FiveCents:Class;
            
            [Embed("assets/10c.png")]

            []
            public var TenCents:Class;

            private function dragIt(event:MouseEvent, value:uint):void 
            {

                // Get the drag initiator component from the event object.
                var dragInitiator:Image = event.currentTarget as Image;
    
                // Create a DragSource object.
                var dragSource:DragSource = new DragSource();
    
                // Add the data to the object.

                dragSource.addData(value, 'value');
    
                // Create a copy of the coin image to use as a drag proxy.
                var dragProxy:Image = new Image();
                dragProxy.source = event.currentTarget.source;
    
                // Call the DragManager doDrag() method to start the drag. 

                DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
            }

        ]]>
    </mx:Script>
    
    <mx:HBox>

        <mx:Image 
            id="oneCent" source="{OneCent}"
            mouseMove="dragIt(event, 1);"

        />
        <mx:Image 
            id="twoCents" source="{TwoCents}"
            mouseMove="dragIt(event, 2);"

        />
        <mx:Image 
            id="fiveCents" source="{FiveCents}"
            mouseMove="dragIt(event, 5);"

        />
        <mx:Image 
            id="tenCents" source="{TenCents}"
            mouseMove="dragIt(event, 10);"

        />        
    </mx:HBox>
    
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.


Drop target events

The drop target can use various events, the most important of which are the dragEnter, dragDrop, and dragExit events.

The dragEnter event

The dragEnter event is dispatched when a drag proxy moves over the drop target from outside the drop target. A component must define an event listener for this event to be a drop target. In the listener, you can change the appearance of the drop target to provide visual feedback to the user that the component can accept the drag operation. For example, you can draw a border around the drop target, or give focus to the drop target.

The dragExit event

The dragExit event is dispatched when the user drags outside the drop target, but does not drop the data onto the target. You can use this event to restore the drop target to its normal appearance if you modified its appearance in response to a dragEnter event or other event.

The dragDrop event

The dragDrop event is dispatched when the user releases the mouse over the drop target. You can use this event listener to add the drag data to the drop target.

In the following example you create a Box container to act as the drop target and define handlers to listen for the dragEnter, dragExit and dragDrop events. The Box container has a Label control inside it that you use to display the total of the coins dropped onto the Box.

In the event handler for the dragEnter event, you check that the drag source contains the "value" format. Only objects that contain this format (i.e., coins in this example) may be dropped on the drop target. If it does, you visually indicate to the user that she may drop the item on the Box by increasing the thickness of the Box container's border. You also inform the DragManager that the Box container will accept the drag initiator by calling its acceptDragDrop() method.

In the event handler for the dragExit event, you restore the visual appearance of the Box container to indicate that the drag proxy is no longer over it.

Finally, in the event handler for the dragDrop event, which gets called after the user has dropped a coin onto the drop target, you increase the value of the totalValue counter by the value of the coin that was dropped on to the Box and revert the Box container to indicate that the drop operation is complete.

Example

<?xml version="1.0" encoding="utf-8"?>

<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    width="525" height="270"
     viewSourceURL="src/DragAndDropDragDropTargetEvents/index.html"
>

    <mx:Script>
        <![CDATA[
            import mx.events.DragEvent;
            import mx.containers.Box;
            import mx.managers.DragManager;
            import mx.core.DragSource;
            
            // Embed the various Euro coin images. Images originally 

            // from Wikipedia (http://en.wikipedia.org/wiki/Euro_coins)
            [Embed("assets/1c.png")]
            []
            public var OneCent:Class;
            
            [Embed("assets/2c.png")]

            []
            public var TwoCents:Class;
            
            [Embed("assets/5c.png")]

            []
            public var FiveCents:Class;
            
            [Embed("assets/10c.png")]

            []
            public var TenCents:Class;
            
            []

            private var totalValue:uint;

            private function dragIt(event:MouseEvent, value:uint):void 
            {

                // Get the drag initiator component from the event object.
                var dragInitiator:Image = event.currentTarget as Image;
    
                // Create a DragSource object.
                var dragSource:DragSource = new DragSource();
    
                // Add the data to the object.

                dragSource.addData(value, 'value');
    
                // Create a copy of the coin image to use as a drag proxy.
                var dragProxy:Image = new Image();
                dragProxy.source = event.currentTarget.source;
    
                // Call the DragManager doDrag() method to start the drag. 

                DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
            }

            // Called if the user drags a drag proxy onto the drop target.
            private function dragEnterHandler(event:DragEvent):void 
            {

                // Get the drop target component from the event object.
                var dropTarget:Box=event.currentTarget as Box;
    
                // Accept the drag only if the user is dragging data 
                // identified by the 'value' format value.

                if (event.dragSource.hasFormat('value')) 
                {
                    // Make the border of the Box thicker to 
                    // visually signal to the user that they can 
                    // drop the coin there.

                    dropTarget.setStyle("borderThickness", 5);
                    
                    // Accept the drop.
                    DragManager.acceptDragDrop(dropTarget);
                }
            }

            
            // Called if the user drags the drag proxy away from the drop target.
            private function dragExitHandler(event:DragEvent):void
            {

                // Get the drop target component from the event object.
                var dropTarget:Box=event.currentTarget as Box;                
                
                // Set the border of the Box to its default value
                // to visually indicate that the user is no longer 
                // over the drop target.

                revertBoxBorder();                
            }                    
            
            // Called if the target accepts the dragged object and the user 
            // releases the mouse button while over the drop target. 
            private function dragDropHandler(event:DragEvent):void 
            {

                // Get the data identified by the color format from the drag source.
                var value:uint = event.dragSource.dataForFormat('value') as uint;

                // Add the value to the total 

                totalValue += value;
                
                // Set the border of the Box to its default value
                revertBoxBorder();                
            }
            
            // Helper method to revert the Box's border to a 1 pixel outline.
            private function revertBoxBorder():void

            {
                amountDisplay.setStyle("borderThickness", 1);                
            }
        ]]>
    </mx:Script>

    
    <mx:HBox>
        <mx:Image 
            id="oneCent" source="{OneCent}"
            mouseMove="dragIt(event, 1);"

        />
        <mx:Image 
            id="twoCents" source="{TwoCents}"
            mouseMove="dragIt(event, 2);"

        />
        <mx:Image 
            id="fiveCents" source="{FiveCents}"
            mouseMove="dragIt(event, 5);"

        />
        <mx:Image 
            id="tenCents" source="{TenCents}"
            mouseMove="dragIt(event, 10);"

        />        
    </mx:HBox>
    
    <mx:Box 
        id="amountDisplay"
        borderStyle="solid" borderColor="#000000" backgroundColor="#FFFFFF"

        width="100%" height="100" horizontalAlign="center" verticalAlign="middle"

        dragEnter="dragEnterHandler(event);"

        dragExit="dragExitHandler(event);"
        dragDrop="dragDropHandler(event);"

    >
        <mx:Label text="{totalValue + ' pence'}" fontSize="48"/>        
    </mx:Box>

    
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.


For more information

About the author

Aral Balkan acts and sings, leads development teams, designs user experiences, architects rich Internet applications, and runs OSFlash.org, the London Macromedia User Group, and his company, Ariaware. He loves talking design patterns and writing for books and magazines. He also authored Arp, the open-source RIA framework for the Flash platform. Aral is generally quite opinionated, animated, and passionate. He loves to smile, and can even chew gum and walk at the same time.