Drag-drop on non-list based controls in Flex/AIR
The List-based controls like List, DataGrid etc will have support for drag and drop. You use drag-drop on list-based contols by enabling properties like dragEnabled and dropEnabled to true. We can implement this drag-drop on non-list based controls as well. To do that we need to handle drag and drop events.
Drag-drop Events for Drag Initiator
- mouseDown, mouseMove: mouseDown event will be dispatched when a control is selected with Mouse button down. mouseMove is dispatched when mouse moves.
- dragStart: this event is dispatched by a list-based control when a drag operation starts. Its handled internally, no need to handle it while implementing on non-list based controls.
- dragComplete: Dispatched when the drag completes.
If you want to implement drag-drop for any component, you must implement either mouseDown or mouseMove and optionally dragComplete event. In case of List-based controls, once dragEnabled property is set to true, Flex automatically adds event handlers for dragStart and dragComplete events.
Drag-Drop events for Drop Target:
- dragEnter: Dispatched when drag proxy moves onto drop target from outside the drop target. Event handler for this must be defined for the component. DragManager.acceptDragDrop() method must be called by event handler to accept drop.
- dragOver: this event is dispatched when mouse is moved over drop target after dragEnter event.
- dragDrop: Dispatched when the mouse is released over drop target.
- dragExit: This event is dispatched when user moves the drag proxy off the target withour dropping the data on the target.
While implementing darg-drop for non-list based controls, we must implement event handlers for dragEnter and dragDrop events and optionally for the remaining two events. Incase of list-based controls, when dropEnabled is set to true, Flex automatically adds event handlers for all the events.
Steps of Drag-Drop Operation:
- First make a component drag initiator. Use mouseDown or mouseMove event handler to start the drag-drop operation. mx.core.DragSource instance is created that contains the data to be dragged and specifies the format of data. mx.managers.DragManager.doDrag() method should be called to initiate the drap-drop operation.
- With mouse button down, if the mouse is moved across the application, Flex displays drag proxy image.
- When this drag proxy is moved over a flex component (which had dragEnter event handler), dragEnter event handler examines the DragSource object to determine whether the data being dragged is in accepted format. To accept the drop, the event handler calls DragManager.acceptDragDrop() method. This method must be called in order for the drop target to receive dragOver, dragExit and dragDrop events.
- If the user releases the drag proxy on the drop target, Flex dispatched dragDrop event. The drop target must define event handler for dragDrop event to add the drag data to the drop target.
Simple Drag-Drop Example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="300" height="300">
<mx:Script>
<![CDATA[
import mx.core.DragSource;
import mx.managers.DragManager;
import mx.events.*;
import mx.containers.Canvas;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Canvas=Canvas(event.currentTarget);
var dragColor:int = dragInitiator.getStyle('backgroundColor');
var ds:DragSource = new DragSource();
ds.addData(dragColor, 'color');
DragManager.doDrag(dragInitiator, ds, event);
}
private function dragEnterHandler(event:DragEvent):void{
if(event.dragSource.hasFormat('color')){
var dropTarget:Canvas=Canvas(event.currentTarget);
DragManager.acceptDragDrop(dropTarget);
}
}
private function dragDropHandler(event:DragEvent):void{
var data:Object = event.dragSource.dataForFormat('color');
myCanvas.setStyle("backgroundColor", data);
}
]]>
</mx:Script>
<mx:HBox x="40" y="40">
<mx:VBox>
<mx:Canvas width="30" height="30" backgroundColor="red" borderStyle="solid" mouseMove="mouseMoveHandler(event)" />
<mx:Canvas width="30" height="30" backgroundColor="blue" borderStyle="solid" mouseMove="mouseMoveHandler(event)" />
<mx:Canvas width="30" height="30" backgroundColor="green" borderStyle="solid" mouseMove="mouseMoveHandler(event)" />
</mx:VBox>
<mx:VBox>
<mx:Label text="Drag into this Canvas" />
<mx:Canvas id="myCanvas" width="100" height="100" backgroundColor="#FFFFFF" borderStyle="solid" dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)" />
</mx:VBox>
</mx:HBox>
</mx:Application>
In this example, we have a canvas to the right which is drop target (which has dragEnter and dragDrop event handlers). Dragging any smaller canvas from the left to the right canvas fills the background of the drop target with the color of the drag initiator.
Result:
Another Example
In the above example, we have the drag Initiator was external to the drop target. We can make the children of a drop target as drag initiators as well.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="400">
<mx:Script>
<![CDATA[
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Canvas=Canvas(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "canvas");
DragManager.doDrag(dragInitiator, ds, event);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("canvas"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
private function dragDropHandler(event:DragEvent):void {
Canvas(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Canvas(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<mx:Canvas id="myCanvas" x="20" y="20" width="300" height="300" backgroundColor="#FFFFFF" borderStyle="solid" dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)">
<mx:Canvas id="thumb" width="50" height="50" borderStyle="solid" backgroundColor="red" mouseMove="mouseMoveHandler(event)" />
</mx:Canvas>
</mx:Application>
In this example, we can drag-drop the red canvas all across the white canvas.
Result:
User-Defined Drag Proxy:
In the above example, while dragging a default drag proxy will be displayed. We can add our own drag proxy image.
In mouseDown or mouseMove event handler, you can optionally specify the drap proxy in doDrag() method. Here are the optional properties to be given incase of user-defined drag proxy:
-
dragImage: Image that specifies the drag proxy
-
xOffset: Specifies the x offset in pixels for the dragImage. Usually it will be negative number.
-
yOffset: Specifies the y offset in pixels for dragImage.Usually it will be negative number.
-
imageAlpha: A number between 0 and 1.0, which specifies the alpha for the drag proxy image. The default value is 0.5
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Image;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/proxy.jpg')]
public var proxyImage:Class;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Canvas=Canvas(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "canvas");
var myProxy:Image = new Image();
myProxy.source = proxyImage;
myProxy.width = 15;
myProxy.height = 15;
DragManager.doDrag(dragInitiator, ds, event, myProxy, -15, -15, 0.8);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("canvas"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
private function dragDropHandler(event:DragEvent):void {
Canvas(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Canvas(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<mx:Canvas id="myCanvas" x="20" y="20" width="300" height="300" backgroundColor="#FFFFFF" borderStyle="solid" dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)">
<mx:Canvas id="thumb" width="50" height="50" borderStyle="solid" backgroundColor="red" mouseMove="mouseMoveHandler(event)" />
</mx:Canvas>
</mx:Application>
You can provide what ever image you want as your drag proxy. Make sure you give the height and width for the drag proxy image, without which it wont work.
Result:
These are the basics for implementing drap-drop for non-list based controls for Flex/AIR.
You can experiment more on this.
Recent Comments
- 1c-rezerv.ru on Adobe Photoshop is 20 Years Old
- Pankaj on Minimizing an AIR App to SystemTray
- Evisong on Drag-drop on non-list based controls in Flex/AIR
- sachin on ADOBE and AVATAR
- rajat goyal on Minimizing an AIR App to SystemTray
Archives
- April 2010 (3)
- March 2010 (2)
- February 2010 (3)
- January 2010 (1)
- December 2009 (15)
- November 2009 (24)
- October 2009 (22)
- September 2009 (24)
- August 2009 (3)
Categories
- Adobe (6)
- Adobe Dreamweaver (1)
- Adobe Illustrator (1)
- Tutorials (1)
- AIR (13)
- Apple (4)
- Applications (2)
- IPhone (1)
- CSS (4)
- Flash (41)
- FL for Digital Home (6)
- Flash Components (2)
- FlashLite (5)
- News (1)
- Websites (2)
- Flash Catalyst (2)
- Flex (9)
- Google (2)
- Icons (1)
- Microsoft (1)
- Photoshop (15)
- Security (1)
- Wordpress (2)
Calender
| M | T | W | T | F | S | S |
|---|---|---|---|---|---|---|
| « Apr | ||||||
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | ||||
October 16th, 2009 - 06:57
Hello from Russia!
Can I quote a post in your blog with the link to you?
October 16th, 2009 - 10:07
Hi Polprav,
sure… thanks…
October 21st, 2009 - 15:23
Hi
please could put another example that uses DragSource
this is very good.
October 21st, 2009 - 23:30
Hi Vasco,
The examples here cover DragSource as well… Let me know if you are looking for anything specific about DragSource…
Thanks
November 4th, 2009 - 13:14
Hi,
How do i control the shifting of objects when dragging it to another position?
For example I want that the upper left corner of the draggeditem does not position itself with the mouse position but as it was positionned just before the drop.
Thanks
November 5th, 2009 - 03:10
Hi Alex,
Could you be more clear….I could not get your point…
Thanks
November 5th, 2009 - 13:48
Ok,
Take the “Another example” example in this tutorial with the red square.
If you drag it you will see that there is a “default proxy” with a green border,
I would like that when I drop the square, it positions itself exactly like the “default proxy” and not positions its upper left corner to the mouse position.
It’s difficult to be more clear.
I hope someone can help me
Thanks
November 9th, 2009 - 09:16
Hi, Could you let me know how to do the same in WindowedApplication(AIR). Drag image never comes up. What could be the issue?I am stuck with that. I am unable to get the drag image working at all
Thanks a lot in advance
Vishal
November 9th, 2009 - 12:51
Is that not clear ?
November 10th, 2009 - 01:34
Hi Vishal,
We have to follow the same procedure even if we want to drag Image. All we have to do here is to create dragSource as Image.
Here’s the code:
(replace ‘<’ with ‘< ' and '>' with '>‘)
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute”>
<mx:Script>
<![CDATA[
import mx.controls.Image;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/proxy.jpg')]
public var proxyImage:Class;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, “image”);
var myProxy:Image = new Image();
myProxy.source = proxyImage;
myProxy.width = 15;
myProxy.height = 15;
DragManager.doDrag(dragInitiator, ds, event, myProxy, -15, -15, 0.8);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat(“image”))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<mx:Canvas id=”myCanvas” x=”20″ y=”20″ width=”300″ height=”300″ backgroundColor=”#FFFFFF” borderStyle=”solid” dragEnter=”dragEnterHandler(event)” dragDrop=”dragDropHandler(event)”>
<mx:Image id=”myImage” width=”50″ height=”50″ source=”@Embed(source=’assets/logo.jpg’)” mouseMove=”mouseMoveHandler(event)” />
</mx:Canvas>
</mx:Application>
November 10th, 2009 - 09:04
Hi Swami,
Thanks for the reply. Its not about dragging images. I am unable to attach a dragImage to a drag operation when done in AIR(WindowedApplication).
Say ther’s one component , out of which I am creating a bitmap and setting as its dragImage in the doDrag method.But the dragImage doesnot show up when the drag happens. It shows as if ther’s no dragImage attached at all. Do you have any working example of dragImage in AIR(WindowedAPplication) ?
Thanks In advance,
Vishal
November 10th, 2009 - 10:15
Swami, could you plz tell me if you know/don’t know how to do what I want or if you don’t understand.
Thanks
November 10th, 2009 - 22:36
Hi Alex, Sorry for the delay…
I got your point. Actually the positioning of dragProxy Image will always be relative to dragInitiator. If you see the doDrag():
DragManager.doDrag(dragInitiator, ds, event, myProxy, -15, -15, 0.8);
The parameters xOffset and yOffset refers to the positioning of dragProxy. If we completely remove these parameters of doDrag(), the dragProxy will be shown always at the top left corner of DragInitiator.
To my knowledge we cannot position the dragProxy at the same location as default dragProxy appears. Its always be relative positioning.
Hope this clears your query… Let me know if its not clear…
Thanks
November 12th, 2009 - 01:36
Hi Vishal,
I tried to implement a simple drag-drop on a button component on AIR. Though i faced an issue while dropping the button using ‘Canvas(event.currentTarget).mouseX;‘, i could able to find a work-around for this.
Here is a sample code for an AIR application wherein applying a dragProxy to a button component while drap-drop:
(replace ‘< ' with '<' and '>‘ with ‘>’ in this code)
<?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.Image;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/proxy.jpg')]
public var proxyImage:Class;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Button=Button(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, “button”);
var myProxy:Image = new Image();
myProxy.source = proxyImage;
myProxy.width = 15;
myProxy.height = 15;
DragManager.doDrag(dragInitiator, ds, event, myProxy, 0, 0,0.8);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat(“button”))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
private function dragDropHandler(event:DragEvent):void {
var p:Point = new Point(event.stageX,event.stageY);
Button(event.dragInitiator).x = event.target.globalToLocal(p).x
Button(event.dragInitiator).y = event.target.globalToLocal(p).y
}
]]>
</mx:Script>
<mx:Canvas id=”myCanvas” x=”20″ y=”20″ width=”300″ height=”300″ backgroundColor=”#FFFFFF” borderStyle=”solid” dragEnter=”dragEnterHandler(event)” dragDrop=”dragDropHandler(event)” >
<mx:Button id=”thumb” width=”40″ height=”20″ mouseMove=”mouseMoveHandler(event)” x=”10″ y=”25″/>
</mx:Canvas>
</mx:WindowedApplication>
Check if this clears your query…
Thanks
November 18th, 2009 - 02:02
Hi Swami,
Thanks for a quick response. Do you see the dragImage in the example you have given above?I used the same example but still the image doesnot show up.What could be the reason?
I am pasting the file
I appreciate you help much.
Vishal
November 18th, 2009 - 02:05
<?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.Image;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/Winter.jpg')]
public var proxyImage:Class;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Button=Button(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, “button”);
var myProxy:Image = new Image();
myProxy.source = proxyImage;
myProxy.width = 100;
myProxy.height = 100;
myProxy.x = 300;
DragManager.doDrag(dragInitiator, ds, event, myProxy, 0, 0,0.8);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat(“button”))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
private function dragDropHandler(event:DragEvent):void {
var p:Point = new Point(event.stageX,event.stageY);
Button(event.dragInitiator).x = event.target.globalToLocal(p).x
Button(event.dragInitiator).y = event.target.globalToLocal(p).y
}
]]>
</mx:Script>
<mx:Canvas id=”myCanvas” x=”20″ y=”20″ width=”300″ height=”300″ backgroundColor=”#FFFFFF” borderStyle=”solid” dragEnter=”dragEnterHandler(event)” dragDrop=”dragDropHandler(event)”>
<mx:Button id=”thumb” width=”40″ height=”20″ mouseMove=”mouseMoveHandler(event)” x=”10″ y=”25″/>
</mx:Canvas>
</mx:WindowedApplication>
November 18th, 2009 - 02:05
Vishal,
Yes, i am able to see the dragImage in the example i gave.
In the above example, the dragProxy image is at ‘/assets/proxy.jpg’. Make sure you give the correct path of the dragProxy image.
Thanks
November 18th, 2009 - 02:24
Vishal,
Its working absolutely fine at my end. Do you see any error?
November 19th, 2009 - 23:58
Swami,
I guess its the problem with the AIR runtime. Coz i dont see the dragImage at all.I discussed this with one of my colleague, and he was saying the same application when launched in MAC gives the dragImage but not in Windows. Even in windows , in some it doesnot. Any insights into the AIR runtime issue???Whats the version of the runtime that you use??? Coz the same app that you gave doesnot give an image in my machine. I cant guess any other reason, do you?
Thanks again,
Vishal
November 20th, 2009 - 04:07
Vishal,
Yes, there are many issues with AIR related to drag-and-drop. Let me find out more about this issue…
The Version of AIR on my machine is 1.5.1.8210. Whats ur AIR Runtime Version?
Thanks
November 20th, 2009 - 07:12
Mine is 1.5.2.8900..I hope we some how find out a solution to this..Thanks much for your efforts on this.
November 27th, 2009 - 06:35
Any updates???
December 1st, 2009 - 00:04
Vishal,
Did you try with AIR 2.0??? Please try with it and let me know if you still face the same issue…
Thanks
January 19th, 2010 - 02:33
Hi Vishal,
We have to follow the same procedure even if we want to drag Image. All we have to do here is to create dragSource as Image.
Here’s the code:
(replace ‘<’ with ‘‘)
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute”>
<mx:Script>
<![CDATA[
import mx.controls.Image;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/proxy.jpg')]
public var proxyImage:Class;
private function mouseMoveHandler(event:MouseEvent):void{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, “image”);
var myProxy:Image = new Image();
myProxy.source = proxyImage;
myProxy.width = 15;
myProxy.height = 15;
DragManager.doDrag(dragInitiator, ds, event, myProxy, -15, -15, 0.8);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat(”image”))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<mx:Canvas id=”myCanvas” x=”20″ y=”20″ width=”300″ height=”300″ backgroundColor=”#FFFFFF” borderStyle=”solid” dragEnter=”dragEnterHandler(event)” dragDrop=”dragDropHandler(event)”>
<mx:Image id=”myImage” width=”50″ height=”50″ source=”@Embed(source=’assets/logo.jpg’)” mouseMove=”mouseMoveHandler(event)” />
</mx:Canvas>
</mx:Application>
BUt it is saying cannot convert Image into canvas…plz help me..i need it urgently..
January 19th, 2010 - 03:06
Hi Sushma,
I am not seeing any such kind of errors. Whats exactly the error thats coming?
Did you try the exact sample which i provided here?
Thanks
January 19th, 2010 - 04:29
The previous one is giving an error saying that cannot convert Image into canvas…plz help me..i need it urgently..
January 19th, 2010 - 05:10
Thks for the quick response swami..
I am not using that proxy..except that everything is same..
January 19th, 2010 - 05:13
Sushma,
Whats the Version of Flex you are using? Are you checking this sample on AIR application or Flex Application? Which platform are you checking it on?
As there are some differences with various Flex SDK versions and there are some issues with AIR when using drag-and-drop.
Thanks
January 28th, 2010 - 02:12
Thank you Charan for quick response..
Everything is wrkng 5n now..thk you..
June 21st, 2010 - 12:02
Hi!
I am seeking answer to a very related issue, and I hope you can provide me a solution for this. I have a button, which is draggable on to a grid/canvas. I do not want the button to move, just create an instance (replicate) of it on-the-fly and make it appear on the canvas/grid, and also retain the original button at the source.
The problem with creating an instance during mouseMove or dragDrop (event capture functions) is that they get created all the time, even when the button is dragged and dropped elsewhere.
Note: I tried using List/DG to do this (dragMoveEnabled=false), and was not successful there.
Thanks,
Rajesh
June 22nd, 2011 - 07:53
I wish I found your article earlier. I investigate into this for a while and I feel lucky to have found the DragManager during reading Flex source code.