To
use a container as a drop target, you must use the backgroundColor property
of the container to set a color. Otherwise, the background color
of the container is transparent, and the Drag and Drop Manager is
unable to detect that the mouse pointer is on a possible drop target.
In the following example, you use the Image control to load a
draggable image into a Canvas container.
You then add event handlers to let the user drag the Image control
within the Canvas container to reposition it:
<?xml version="1.0"?>
<!-- dragdrop\DandDImage.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// initiates the drag-and-drop operation.
private function mouseMoveHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
DragManager.doDrag(dragInitiator, ds, event);
}
// The dragEnter event handler for the Canvas container
// enables dropping.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</fx:Script>
<!-- The Canvas is the drag target -->
<mx:Canvas id="v1"
width="500" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);">
<!-- The image is the drag initiator. -->
<s:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseMoveHandler(event);"/>
</mx:Canvas>
</s:Application>
The executing SWF file for the previous example is shown below:
Example: Setting the drag indicator for Spark controls
The drag indicator defines the appearance of the dragged
data during drag-and-drop operations. The appearance of the dragged
data is determined by the item renderer for the list-based control.
Spark item renderers support the optional dragging view
state that you can use to control the appearance of the drag indicator.
The following item renderer add the dragging view
state to display the dragged data in a bold, blue italic font:
The executing SWF file for the previous example is shown below:
Example: Specifying the drag indicator by using the DragManager
In the event handler for the mouseDown or mouseUp event,
you can optionally specify a drag indicator in the doDrag()
method of the DragManager class.
If you do not specify a drag indicator, Flex uses a default drag
indicator. The doDrag() method takes the following
optional arguments to specify the drag indicator and its properties.
Argument
Description
dragIndicator
The image that defines the drag indicator.
To
specify a symbol, such as a JPEG image of a product that a user
wants to order, use a string that specifies the symbol’s name, such
as myImage.jpg.
To specify a component, such as a Flex container
or control, create an instance of the control or container, configure
and size it, and then pass it as an argument to the doDrag() method.
xOffset
Number that specifies the x offset, in pixels,
for the dragImage. This argument is optional. If
omitted, the drag indicator is shown at the upper-left corner of
the drag initiator. The offset is expressed in pixels from the left
edge of the drag indicator to the left edge of the drag initiator,
and is usually a negative number.
yOffset
Number that specifies the y offset, in pixels,
for the dragImage. This argument is optional. If
omitted, the drag indicator is shown at the upper-left corner of
the drag initiator. The offset is expressed in pixels from the top
edge of the drag indicator to the top edge of the drag initiator,
and is usually a negative number.
imageAlpha
A Number that specifies the alpha value
used for the drag indicator image. If omitted, Flex uses an alpha
value of 0.5. A value of 0 corresponds to transparent and a value
of 1.0 corresponds to fully opaque.
You must specify a size for the drag indicator, otherwise it
does not appear. The following example modifies the example in Example: Using a container as a drop target to use a 15 pixel by 15
pixel Image control
as the drag indicator:
<?xml version="1.0"?>
<!-- dragdrop\DandDImageProxy.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// initiates the drag-and-drop operation.
private function mouseOverHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
// The drag manager uses the Image control
// as the drag indicator and sets the alpha to 1.0 (opaque),
// so it appears to be dragged across the Canvas.
var imageProxy:Image = new Image();
imageProxy.source = globeImage;
imageProxy.height=15;
imageProxy.width=15;
DragManager.doDrag(dragInitiator, ds, event,
imageProxy, -15, -15, 1.00);
}
// The dragEnter event handler for the Canvas container
// enables dropping.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</fx:Script>
<!-- The Canvas is the drag target -->
<mx:Canvas id="v1"
width="500" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);">
<!-- The image is the drag initiator. -->
<s:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseOverHandler(event);"/>
</mx:Canvas>
</s:Application>
The executing SWF file for the previous example is shown below:
To use a control with specific contents, such as a VBox control
with a picture and label, you must create a custom component that
contains the control or controls, and use an instance of the component
as the dragIndicator argument.
Example: Setting the drop indicator for Spark controls
The drop indicator shows where the dragged data will be
inserted into the drop target. The appearance of the drop indicator
is controlled by the skin class of the drop target. By default,
the drop indicator for a Spark control is a solid line that spans
the width of the control.
You can create a custom drop indicator by creating a custom skin
class for the drop target. In your skin class, create a skin part
named dropIndicator in the <fx:Declarations> area
of the skin class, as the following example shows:
This code shows an excerpt from the MyListSkin.mxml file, a custom
skin class for the Spark List control. The lines define the drop
indicator to be a blue arrow that appears in the drop target to
indicate where the dragged data is added.
Note that the bounding Group container specifies the maxWidth and maxHeight properties.
For the drop indicator, only the setting along the major axis of
the control is applied. For example, for a List class using vertical
layout, the x-axis is the major axis. Therefore, the maxHeight property
is applied and the maxWidth property is ignored.
The Spark layout classes use the following rules to size and
position the drop indicator:
The drop indicator’s size
is calculated to be as big as the gap between the neighboring data
items in the control.
Any minimum or maximum setting in the
major axis of orientation is honored. Along the minor axis, minimum
and maximum settings are ignored. The drop indicator is sized to
be as wide as the respective column and as tall as the respective
row.
After drop indicator is sized, it is centered within the
gap between the data items.
The following example uses the MyListSkin.mxml skin class:
The executing SWF file for the previous example is shown below:
Example: Setting the cursor styles of the DragManager
The DragManager uses styles to control the display of the
different cursors used during the drag and drop operation, such
as the move and copy cursors. The cursors are defined as symbols
in the Assets.swf file in the flexInstallDir\frameworks\projects\framework\assets
directory.
By default, Flex defines the cursor styles as if you had used
the following type selector in your application:
The executing SWF file for the previous example is shown below:
Example: Handling the dragOver and dragExit events for the drop target
The dragOver event occurs when the user
moves the mouse over a drag-and-drop target whose dragEnter event
handler has called the DragManager.acceptDragDrop() method.
This event is dispatched continuously as the user drags the mouse
over the target. The dragOver event handler is
optional; you do not have to define it to perform a drag‑and-drop operation.
The dragOver event is useful for specifying
the visual feedback that the user gets when the mouse is over a
drop target. For example, you can use the DragManager.showFeedback() method
to specify the drag-feedback indicator that appears along with the
drag indicator. This method uses four constant values for the argument,
as the following table shows:
Argument value
Icon
DragManager.COPY
A green circle with a white plus sign indicating
that you can perform the drop.
DragManager.LINK
A grey circle with a white arrow sign indicating
that you can perform the drop.
DragManager.MOVE
A plain arrow indicating that you can perform
the drop.
DragManager.NONE
A red circle with a white x appears
indicating that a drop is prohibited. This is the same image that
appears when the user drags over an object that is not a drag target.
You typically show the feedback indicator based on the keys pressed
by the user during the drag-and-drop operation. The DragEvent object
for the dragOver event contains Boolean properties
that indicate whether the Control or Shift keys are pressed at the
time of the event: ctrlKey and shiftKey,
respectively. No key pressed indicates a move, the Control key indicates
a copy, and the Shift key indicates a link. You then call the showFeedback() method
as appropriate for the key pressed.
Another use of the showFeedback() method is
that it determines the value of the action property
of the DragEvent object for the dragDrop, dragExit, and dragComplete events.
If you do not call the showFeedback() method in
the dragOver event handler, the action property
of the DragEvent is always set to DragManager.MOVE.
The dragExit event is dispatched when the user
drags the drag indicator off the drop target, but does not drop
the data onto the target. You can use this event to restore any
visual changes that you made to the drop target in the dragOver event
handler.
In the following example, you set the dropEnabled property
of a List control to true to configure it as a
drop target and to use the default event handlers. However, you
want to provide your own visual feedback, so you also define event handlers
for the dragEnter, dragExit, and dragDrop events.
The dragOver event handler completely overrides
the default event handler, so you call the Event.preventDefault() method
to prohibit the default event handler from execution.
The dragOver event handler determines whether
the user is pressing a key while dragging the drag indicator over
the target, and sets the feedback appearance based on the key that
is pressed. The dragOver event handler also sets
the border color of the drop target to green to indicate that it
is a viable drop target, and uses the dragExit event
handler to restore the original border color.
For the dragExit and dragDrop handlers,
you only want to remove any visual changes that you made in the dragOver event
handlers, but otherwise you want to rely on the default Flex event
handlers. Therefore, these event handlers do not call the Event.preventDefault() method:
<?xml version="1.0"?>
<!-- dragdrop\DandDListToListShowFeedbackSpark.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="initApp();">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.DragEvent;
import mx.managers.DragManager;
import spark.layouts.supportClasses.DropLocation;
private function initApp():void {
firstList.dataProvider = new ArrayCollection([
{label:"First", data:"1"},
{label:"Second", data:"2"},
{label:"Third", data:"3"},
{label:"Fourth", data:"4"}
]);
secondList.dataProvider = new ArrayCollection([]);
}
// Variable to store original border color.
private var tempBorderColor:uint;
// Flag to indicate that tempBorderColor has been set.
private var borderColorSet:Boolean = false;
private function dragOverHandler(event:DragEvent):void {
// Explpicitly handle the dragOver event.
event.preventDefault();
// Since you are explicitly handling the dragOver event,
// call showDropIndicator() to have the drop target
// display the drop indicator.
// The drop indicator is removed
// automatically for the list controls by the built-in
// event handler for the dragDrop event.
var dropLocal:DropLocation =
event.currentTarget.layout.calculateDropLocation(event);
event.currentTarget.layout.showDropIndicator(dropLocal);
if (event.dragSource.hasFormat("itemsByIndex"))
{
// Set the border to green to indicate that
// this is a drop target.
// Since the dragOver event is dispatched continuosly
// as you move over the drop target, only set it once.
if (borderColorSet == false) {
tempBorderColor =
event.currentTarget.getStyle('borderColor');
borderColorSet = true;
}
// Set the drag-feedback indicator based on the
// type of drag-and-drop operation.
event.currentTarget.setStyle('borderColor', 'green');
if (event.ctrlKey) {
DragManager.showFeedback(DragManager.COPY);
return;
}
else if (event.shiftKey) {
DragManager.showFeedback(DragManager.LINK);
return;
}
else {
DragManager.showFeedback(DragManager.MOVE);
return;
}
}
// Drag not allowed.
DragManager.showFeedback(DragManager.NONE);
}
private function dragDropHandler(event:DragEvent):void {
dragExitHandler(event);
}
// Restore the border color.
private function dragExitHandler(event:DragEvent):void {
event.currentTarget.setStyle('borderColor', tempBorderColor);
borderColorSet = true;
}
]]>
</fx:Script>
<s:HGroup id="myHG">
<s:List id="firstList"
dragEnabled="true"
dragMoveEnabled="true"/>
<s:List id="secondList"
dropEnabled="true"
dragOver="dragOverHandler(event);"
dragDrop="dragExitHandler(event);"
dragExit="dragExitHandler(event);"/>
</s:HGroup>
<s:Button id="b1"
label="Reset"
click="initApp();"/>
</s:Application>
The executing SWF file for the previous example is shown below: