Flex中的拖动技术

来源:互联网 发布:实况足球拜仁数据扯淡 编辑:程序博客网 时间:2024/05/07 22:45

 

 Flex中的拖动技术

 

 

网上发现这篇文章很详细,稍作补充整理下!

组件的拖动分为:加强型(即本身就可以拖动设置是否可以拖动的属性即可),非加强型(可以通过DragManager,DragEvent,DragSource三个类来实现)

下面详细讲解常见的拖动,案例比较多,可以自行类推和拓展!

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" fontSize="12"><mx:Script>    <![CDATA[        import mx.collections.ArrayCollection;        import mx.core.IUIComponent;        import mx.events.DragEvent;        import mx.core.DragSource;        import mx.managers.DragManager;              [Bindable]        private var listData:ArrayCollection = new ArrayCollection();        //拖动初始器        private function dragSource(myData:String,e:MouseEvent,format:String):void        {           var iu:IUIComponent = e.currentTarget as IUIComponent;            var ds : DragSource = new DragSource();            ds.addData(myData,format);//设置一个标号format            DragManager.doDrag(iu,ds,e); // 开始拖动这个物体        }        //当拖进去时        private function onEnter( e:DragEvent,format:String ) : void        {            if(e.dragSource.hasFormat(format))//如果标号为format则接受拖来的物体            {                DragManager.acceptDragDrop(IUIComponent(e.target) );// 接受被拖进来的物体                    }        }        //当拖完成时        private function onDrop(e:DragEvent,format:String) : void        {            var myData:Object = new Object();            myData = e.dragSource.dataForFormat(format);            list1.dataProvider.addItem(myData);//list1是List的id,要是扩展到其他组件,改这里就可以了。        }    ]]></mx:Script>    <mx:Label text="拖动我到List" width="86" height="27" id="lbl" mouseDown="dragSource('这个是一个label',event,'stringFormat')"/>    <mx:List dataProvider="{listData}" id="list1" dragEnter="onEnter(event,'stringFormat')"dragDrop="onDrop(event,'stringFormat')" width="206"></mx:List>        <!--文档注释-->     </mx:Application>

Flex组件内置了处理拖拽事件的接口,有些控件已经实现了拖拽功能,比如List、DataGrid、Menu、

HorizontalList、 PrintDataGrid、TileList、Tree,在设置相关的拖拽属性后,它们都可以在相同类型的组
件之间利用鼠标来实现数据的转移。
allowDragSelection           是否可以拖选
allowMultipleSelection       是否可以多选
dragEnabled                     是否可以拖动子元素
dragMoveEnabled              是否移动元素位置,而不是复制元素
dropEnabled                     是否可以将物体放置进来


在Flex中,有几个专门的对象供开发者处理拖拽事件:
DragManager:位于mx.managers包中,管理拖拽事件
DragSource:   位于mx.core包中,是Flex框架中的核心成员,处理拖拽中的数据传递
DragEvent:     位于mx.events包中,拖拽操作中的事件对象。


按照逻辑,拖拽中至少有两个对象:一方提供数据,一方接收数据。在这个过程中,提供数据的一方按照前后
顺序,可以把整个过程划分为下面几个事件:

mouseDown:鼠标按下。
mouseMove:鼠标移动。
dragComplate:鼠标释放。判断目标是否接受数据,如果可以,拖放成功。


接收方也将经历几个阶段
dragEnter:被拖动对象移动到目标范围中。
dragDrop:鼠标在目标上松开。
dragOver:鼠标移动到目标上。
dragExit:独享被拖离目标范围。


1.   Tree与Tree之间的拖动:

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"layout="vertical"verticalAlign="middle"><mx:XML id="myData"><data><item label="ActionScript"><item label="Flash"/><item label="Flex"/></item><item label="Mirage"></item><item label="JavaScript"/></data></mx:XML><mx:XML id="copyData"><data><item label="JavaScript"/></data></mx:XML><mx:Tree dropEnabled="true" dragEnabled="true" dragMoveEnabled="true" allowMultipleSelection="true" dataProvider="{myData.item}" labelField="@label"/><mx:Tree dropEnabled="true" dataProvider="{copyData.item}" labelField="@label"/></mx:Application>


 

上面代码中只需设置
dropEnabled="true" //是否可以将被拖动的物体放置进来
dragEnabled="true" //是否可以拖动子元素
dragMoveEnabled="true" //是否只是移动元素,而不是复制元素
allowMultipleSelection="true" //是否可以多项拖动元素,为true时可以用ctrl选多个一起拖动


List与List之间的拖动,只要设置上面的就可以了。
DataGrid 拖动到DataGrid和List

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"layout="vertical"verticalAlign="middle"fontSize="12"><mx:Script><![CDATA[import mx.collections.ArrayCollection;import mx.events.DragEvent;[Bindable]private var mylist:ArrayCollection;//当拖完成时private function onDrop(e:DragEvent):void{var myData:Object=new Object();myData=e.dragSource.dataForFormat('items'); //从dragSource中拿到条目var name:String=myData[0].name; //注意这个地方必需要用变量进行替换list1.dataProvider.addItem(name);e.preventDefault(); //可以去掉默认的数据转移}]]></mx:Script><mx:XMLList id="employees"><employee><name>小马</name><phone>13042334532</phone><email>liuhai@163.com</email></employee><employee><name>张春</name><phone>13642987532</phone><email>zhang@sina.com</email></employee><employee><name>小李</name><phone>13923485844</phone><email>xiaoli@qq.com</email></employee></mx:XMLList><mx:DataGrid x="10" y="15" width="277" id="dg" rowCount="5" dataProvider="{employees}" dragEnabled="true"><mx:columns><mx:DataGridColumn headerText="Name"   dataField="name"/><mx:DataGridColumn headerText="Email"   dataField="email"/><mx:DataGridColumn headerText="Phone"   dataField="phone"/></mx:columns></mx:DataGrid><mx:DataGrid dropEnabled="true"><mx:columns><mx:DataGridColumn headerText="Name"   dataField="name"/><mx:DataGridColumn headerText="Email"   dataField="email"/><mx:DataGridColumn headerText="Phone"   dataField="phone"/></mx:columns></mx:DataGrid><mx:List height="210" width="206" id="list1" dropEnabled="true" dataProvider="{mylist}" dragDrop="onDrop(event)"></mx:List>  </mx:Application>

2.非加强拖动技术
Label的拖动,可以扩展到其他组件


 

Button的拖动,可以扩展到其他组件

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"layout="vertical"verticalAlign="middle"fontSize="12"><mx:Script><![CDATA[import mx.core.IUIComponent;import mx.events.DragEvent;import mx.core.DragSource;import mx.managers.DragManager;//拖动初始器private function dragSource(e:MouseEvent, format:String):void{var iu:IUIComponent=e.currentTarget as IUIComponent;var ds:DragSource=new DragSource();ds.addData({"x": e.localX, "y": e.localY}, format); //设置一个标号formatDragManager.doDrag(iu, ds, e);}//当拖进去时private function onEnter(e:DragEvent, format:String):void{if (e.dragSource.hasFormat(format)) //如果标号为format则接受拖来的物体{DragManager.acceptDragDrop(IUIComponent(e.target));}}//当拖完成时private function onDrop(e:DragEvent, format:String):void{var myData:Object=new Object();myData=e.dragSource.dataForFormat(format);btn.x=this.mouseX - myData.x; //btn为按钮的id,要是扩展到其他组件,改这里就可以了。btn.y=this.mouseY - myData.y;}]]></mx:Script><mx:Canvas y="40"   id="cansAccess"   backgroundColor="#000000"   width="300"   height="200"   dragEnter="onEnter(event,'formatString')"   dragDrop="onDrop(event,'formatString')"/><mx:Button id="btn"   label="拖动我到面板"   mouseDown="dragSource(event,'formatString')"/> </mx:Application>


 

一定要注意,标签的先后位置,Button 要在Canvas 之后.


3.Canvas容器中拖动Box,你还可以在Box中添加图片等。

 

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"layout="absolute"fontSize="12"><mx:Script><![CDATA[import mx.containers.Box;import mx.containers.Canvas;import mx.core.IUIComponent;import mx.events.DragEvent;import mx.managers.DragManager;import mx.core.DragSource;//拖动初始器private function dragSource(e:MouseEvent, format:String):void{var iu:IUIComponent=e.currentTarget as IUIComponent;var ds:DragSource=new DragSource();ds.addData(iu, format); //设置一个标号formatDragManager.doDrag(iu, ds, e); // 开始拖动这个物体}//当拖进去时private function onEnter(e:DragEvent, format:String):void{if (e.dragSource.hasFormat(format)) //如果标号为format则接受拖来的物体{DragManager.acceptDragDrop(IUIComponent(e.target)); // 接受被拖进来的物体      }}//当拖完成时private function onDrop(e:DragEvent, format:String):void{var box:Box=Box(e.dragInitiator); //如果扩展到其他组件,改这里Box就可以了。box.x=e.localX;box.y=e.localY;}]]></mx:Script><mx:Canvas backgroundColor="0xEEEEEE"   width="500"   height="246"   horizontalCenter="0"   verticalCenter="0"   dragEnter="onEnter(event,'boxFormat')"   dragDrop="onDrop(event,'boxFormat')"><mx:Box id="boxDrag"width="20"height="20"backgroundColor="0x00FFCC"x="97"y="47"mouseDown="dragSource(event,'boxFormat');"></mx:Box></mx:Canvas> </mx:Application>


 

4.图片的拖动

 

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"layout="vertical"width="100%"height="100%"fontSize="12"><mx:Script><![CDATA[private var oldX:Number; //拖动开始是的坐标private var oldY:Number;//拖动开始private function dragStart(event:MouseEvent):void{oldX=event.stageX; //相对Application的坐标oldY=event.stageY;}//拖动结束private function dragEnd(event:MouseEvent):void{lbl.text="Local (x,y):" + event.localX.toString() + "," + event.localX.toString(); //相对图片的坐标lbl2.text="Stage (x,y):" + event.stageX.toString() + "," + event.stageY.toString(); //相对Application的坐标if (event.buttonDown){ //如果鼠标在移动过程中并且按下,也就是说鼠标的拖动事件。var x:Number=event.stageX - oldX; //相对Application的坐标的移动量var y:Number=event.stageY - oldY;oldX=event.stageX; //更新拖动开始是的坐标oldY=event.stageY;img.move(img.x + x, img.y + y); //img是 Image的id,如果扩展到其他组件,改这里就可以了。}}]]></mx:Script><mx:Label x="10"  y="10"  text=""  id="lbl"/><mx:Label x="10"  y="27"  text=""  id="lbl2"/><mx:Panel x="257"  y="71"  width="700"  height="80%"  layout="absolute"  horizontalScrollPolicy="off"  verticalScrollPolicy="off"  title="图片在面板中的拖动例子"  fontSize="12"><mx:Image id="img"  x="0"  y="0"  source="test.JPG"  mouseMove="dragEnd(event)"  mouseDown="dragStart(event)"/></mx:Panel> </mx:Application>


 

5.从外部拖动到组件,比如从桌面上拖动一个图片到图片组件等。
因为我的flash包中没有flash.events.NativeDragEvent等。所以这里稍作总结。

拖动外部文件

拖动外部文件需要NativeDragEvent,NativeDragManager类。其实用法和上面的DragManager一样,但是往往一个控件既要接受Flex内部被拖进来的控件,还要接受外部拖进来的文件,这时候显得就比较麻烦了。
但是请不要害怕,这里的Clipboard会帮我解决问题。

 

<mx:Canvas y="40" id="cansAccess" backgroundColor="#000000"  width="300" height="200" dragDrop="complete(event)" nativeDragDrop="nativeComplete(event)" dragEnter="enter(event)" /><mx:Button id="btnDrag" label="拖动我" mouseDown="doDrag( event )" />

按理来说当拖动内部控件的时候会触发dragDrop事件,拖动外部文件会触发nativeDragDrop事件,事实上,不管你拖动外部文件还是内部控件都会触发这两个事件。这里我们使用Clipboard来解决这一麻烦


 

private function doDrag( e : MouseEvent ) : void{ var ds : DragSource = new DragSource; ds.addData( {"x" : e.localX, "y" : e.localY},"xy"); DragManager.doDrag(btnDrag,ds,e);}private function enter( e  :DragEvent ) : void{ DragManager.acceptDragDrop( Canvas(e.target) ); NativeDragManager.acceptDragDrop(Canvas(e.target)); //使其接受从外部拖进来的文件 }private function complete( e : DragEvent ) : void{ }private function nativeComplete( e : NativeDragEvent ) : void{ var filesObj : Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT ) as Array; //获取剪切板上的文件列表 if( filesObj &&  filesObj.length > 0)  //符合这一条件说明是从外部拖文件进来  这里假设处理拖进来的是图片 {  for each( var item : File in filesObj )  {   switch( item.extension )   {    case "jpg":    case "bmp":    case "gif":    var img : Image = new Image;     img.source = item.nativePath;     cansAccess.addChild( img );    break;      }  } } else   //否则的话是就是在拖动内部的控件 {  var xy : Object =  e.clipboard.getData(e.clipboard.formats[0]);  //还记得doDrag 的时候附加的那个 DragSource 么?  //这里因为不能用e.dragSource.dataForFormat("xy")了因为事件不一样,  //但我们还是可以用剪切板来取得这个值  btnDrag.x =  e.localX - xy.x + cansAccess.x;  btnDrag.y =  e.localY - xy.y + cansAccess.y; }}






6.引入dNdLib.swc库让拖动变得更简单
Flex开放了它的拖拽库(即:flex-drag-n-drop-lib),我们可以利用它做一些很有用的拖拽应用,下面我们

来做一个简单的示例,按照下述的步骤,你会了解到在Flex中使用flex-drag-n-drop-lib的技巧。
1.点击这里下载SWC组件到你的桌面。
2.打开FlexBuilder,新建一个Flex Project,在第三步的Library Path选项中,点击Add SWC按钮,将刚才下

载到的SWC组件引入到项目中。


3.点击Finish,在自动创建的MXML文件中,敲入以下代码:

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"layout="absolute"xmlns:containers="dNdLib.containers.*"fontSize="12"><mx:Script><![CDATA[import dNdLib.managers.DnDManager;]]></mx:Script><containers:DnDContainer borderStyle="solid" id="left" backgroundColor="#FFFFFF" width="161" height="237" x="110" y="168"><mx:Button label="拖动我"   mouseDown="DnDManager.getInstance().doDrag(event)"   width="92"   height="32"/><mx:CheckBox label="拖动就这么简单" mouseDown="DnDManager.getInstance().doDrag(event)"/></containers:DnDContainer><containers:DnDContainer borderStyle="solid" id="bottom" backgroundColor="#FFFFFF" x="415" y="168" width="140" height="237"/></mx:Application>

然后Run一下看看结果吧,组件可以拖动了。很简单吧。
注意:必须为DnDContainer设置一个背景色(backgroundColor=color),否则可能无法产生相应区域。

原创粉丝点击