<?xml version="1.0" encoding="utf-8"?> <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" xmlns:vicp="net.myflex.vicp.*" minWidth="955" minHeight="600" backgroundColor="0"> <fx:Declarations> </fx:Declarations> <fx:Style source="assets/style.css"/> <vicp:DragPanel x="300" y="112" width="225" height="349"> </vicp:DragPanel> </s:Application>
面板:
/** * 黄记新 */ package net.myflex.vicp { import flash.display.DisplayObject; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import mx.core.FlexGlobals; import mx.core.UIComponent; import mx.events.FlexEvent; import spark.components.Group; import spark.components.Panel; public class DragPanel extends Panel { /////////// 皮肤类 [SkinPart] public var topGroup:Group; [SkinPart] public var dragAdorner:Adorner; private var dragRect:Rectangle;//拖拽矩形框; private var isDocked:Boolean;//停靠标志变量; private var isMouseIn:Boolean; /////////// 构造函数 private var oPoint:Point = new Point(); private var oW:Number; private var oH:Number; private var resizing:Boolean; public function DragPanel() { super(); addEventListener(FlexEvent.CREATION_COMPLETE,completeHandler); } private function completeHandler(event:FlexEvent):void{ addEventListeners(); setSize(); } private function setSize():void{ this.oH=this.height; this.oW=this.width; } protected function addEventListeners():void{ this.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); } protected function mouseOverHandler(event:MouseEvent):void{ if(this.isDocked && !resizing){ this.y=0; } this.addEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler); this.removeEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); event.stopPropagation(); this.dragAdorner.visible=true; } protected function mouseOutHandler(event:MouseEvent):void{ this.removeEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler); this.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); event.stopPropagation(); if(this.isDocked && !resizing){ this.y=-this.height+4; } this.dragAdorner.visible=false; } /** * 皮肤添加 * @param partName * @param instance * */ override protected function partAdded(partName:String, instance:Object):void{ super.partAdded(partName,instance); if(instance==topGroup){ topGroup.addEventListener(MouseEvent.MOUSE_DOWN,topGroupMouseDownHandler); } if(instance==this.dragAdorner){ dragAdorner.addEventListener(MouseEvent.MOUSE_DOWN,dragAdornerMouseDownHandler); } } /** * 皮肤移除 * @param partName * @param instance * */ override protected function partRemoved(partName:String, instance:Object):void{ super.partRemoved(partName,instance); if(instance==topGroup){ topGroup.removeEventListener(MouseEvent.MOUSE_DOWN,topGroupMouseDownHandler); } } /** * 边式按下响应函数 * @param event * */ protected function dragAdornerMouseDownHandler(event:MouseEvent):void{ event.stopPropagation(); this.oPoint.x = mouseX; this.oPoint.y = mouseY; this.oPoint = this.localToGlobal(oPoint); FlexGlobals.topLevelApplication.parent.addEventListener(MouseEvent.MOUSE_MOVE,dragAdornerMouseMoveHandler); FlexGlobals.topLevelApplication.parent.addEventListener(MouseEvent.MOUSE_UP,dragAdornerMouseUpHandler); } /** * 移动; * @param event * */ protected function dragAdornerMouseMoveHandler(event:MouseEvent):void{ event.stopPropagation(); var xPlus:Number = FlexGlobals.topLevelApplication.parent.mouseX - this.oPoint.x; var yPlus:Number = FlexGlobals.topLevelApplication.parent.mouseY - this.oPoint.y; this.width = this.oW + xPlus < 140 ? 140:this.oW + xPlus; this.height=this.oH+yPlus< 140 ? 140:this.oH+yPlus; resizing=true; } /** * 边式弹起,移除侦听,重置局部变量; * @param event * */ protected function dragAdornerMouseUpHandler(event:MouseEvent):void{ event.stopPropagation(); FlexGlobals.topLevelApplication.parent.removeEventListener(MouseEvent.MOUSE_MOVE,dragAdornerMouseMoveHandler); FlexGlobals.topLevelApplication.parent.removeEventListener(MouseEvent.MOUSE_UP,dragAdornerMouseUpHandler); setSize(); resizing=false; } /** * 拖拽,侦听鼠标弹起; * @param event * */ protected function topGroupMouseDownHandler(event:MouseEvent):void{ if(!this.dragRect){ this.dragRect=new Rectangle(this.parent.x,this.parent.y,this.parent.width,this.parent.height); } this.dragRect.width=this.parent.width-this.width; this.dragRect.height=this.parent.height-this.height; this.startDrag(); // this.startDrag(false,this.dragRect); this.topGroup.addEventListener(MouseEvent.MOUSE_UP,topGroupMouseUpHandler); var sandBoxRoot:DisplayObject=this.systemManager.getSandboxRoot(); sandBoxRoot.addEventListener(MouseEvent.MOUSE_UP,topGroupMouseUpHandler); event.stopPropagation(); } /** * 停止拖拽,移除鼠标弹起侦听; * @param event * */ protected function topGroupMouseUpHandler(event:MouseEvent):void{ this.stopDrag(); this.topGroup.removeEventListener(MouseEvent.MOUSE_UP,topGroupMouseUpHandler); var sandBoxRoot:DisplayObject=this.systemManager.getSandboxRoot(); sandBoxRoot.removeEventListener(MouseEvent.MOUSE_UP,topGroupMouseUpHandler); if(this.y<=0){ this.isDocked=true; this.y=-4; }else{ this.isDocked=false; } event.stopPropagation(); } } }
边饰:
package net.myflex.vicp { import flash.events.MouseEvent; import flash.geom.Point; import mx.core.FlexGlobals; import mx.core.IVisualElement; import mx.core.UIComponent; import spark.components.Application; import spark.components.supportClasses.SkinnableComponent; public class Adorner extends SkinnableComponent { private var _resizedEle:UIComponent; private var _point:Point=new Point(); public function Adorner() { super(); } public function get resizedEle():UIComponent { return _resizedEle; } public function set resizedEle(value:UIComponent):void { _resizedEle = value; } private function mouseDownHandler(event:MouseEvent):void{ } private function mouseMoveHandler(event:MouseEvent):void{ } private function mouseUpHandler(event:MouseEvent):void{ } } }
DragPanelSkin.mxml
<?xml version="1.0" encoding="utf-8"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="131" minHeight="127" blendMode="normal" mouseEnabled="false" alpha.disabled="0.5" alpha.disabledWithControlBar="0.5" xmlns:vicp="net.myflex.vicp.*"> <fx:Metadata>[HostComponent("net.myflex.vicp.DragPanel")]</fx:Metadata> <fx:Script fb:purpose="styling"> <![CDATA[ import mx.core.FlexVersion; /* Define the skin elements that should not be colorized. For panel, border and title background are skinned, but the content area, background, border, and title text are not. */ static private const exclusions:Array = ["background", "titleDisplay", "contentGroup", "controlBarGroup", "border"]; /* exclusions before Flex 4.5 for backwards-compatibility purposes */ static private const exclusions_4_0:Array = ["background", "titleDisplay", "contentGroup", "controlBarGroup"]; /** * @private */ override public function get colorizeExclusions():Array { // Since border is styleable via borderColor, no need to allow chromeColor to affect // the border. This is wrapped in a compatibility flag since this change was added // in Flex 4.5 if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5) { return exclusions_4_0; } return exclusions; } /** * @private */ override protected function initializationComplete():void { useChromeColor = true; super.initializationComplete(); } /** * @private */ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { if (getStyle("borderVisible") == true) { border.visible = true; background.left = background.top = background.right = background.bottom = 1; contents.left = contents.top = contents.right = contents.bottom = 1; } else { border.visible = false; background.left = background.top = background.right = background.bottom = 0; contents.left = contents.top = contents.right = contents.bottom = 0; } dropShadow.visible = getStyle("dropShadowVisible"); var cr:Number = getStyle("cornerRadius"); var withControls:Boolean = (currentState == "disabledWithControlBar" || currentState == "normalWithControlBar"); if (cornerRadius != cr) { cornerRadius = cr; dropShadow.tlRadius = cornerRadius; dropShadow.trRadius = cornerRadius; dropShadow.blRadius = withControls ? cornerRadius : 0; dropShadow.brRadius = withControls ? cornerRadius : 0; setPartCornerRadii(topMaskRect, withControls); setPartCornerRadii(border, withControls); setPartCornerRadii(background, withControls); } if (bottomMaskRect) setPartCornerRadii(bottomMaskRect, withControls); borderStroke.color = getStyle("borderColor"); borderStroke.alpha = getStyle("borderAlpha"); backgroundFill.color = getStyle("backgroundColor"); backgroundFill.alpha = getStyle("backgroundAlpha"); super.updateDisplayList(unscaledWidth, unscaledHeight); } /** * @private */ private function setPartCornerRadii(target:Rect, includeBottom:Boolean):void { target.topLeftRadiusX = cornerRadius; target.topRightRadiusX = cornerRadius; target.bottomLeftRadiusX = includeBottom ? cornerRadius : 0; target.bottomRightRadiusX = includeBottom ? cornerRadius : 0; } private var cornerRadius:Number; ]]> </fx:Script> <s:states> <s:State name="normal"/> <s:State name="disabled"/> <s:State name="normalWithControlBar" stateGroups="withControls"/> <s:State name="disabledWithControlBar" stateGroups="withControls"/> </s:states> <!-- drop shadow can't be hittable so it stays sibling of other graphics --> <!--- @private --> <s:RectangularDropShadow id="dropShadow" left="0" right="0" top="0" bottom="0" alpha="0.32" angle="90" blurX="20" blurY="20" color="#000000" distance="11"/> <!-- drop shadow can't be hittable so all other graphics go in this group --> <s:Group left="0" right="0" top="0" bottom="0"> <!-- top group mask --> <!--- @private --> <s:Group id="topGroupMask" left="1" right="1" top="1" bottom="1"> <!--- @private --> <s:Rect id="topMaskRect" left="0" right="0" top="0" bottom="0"> <s:fill> <s:SolidColor alpha="0"/> </s:fill> </s:Rect> </s:Group> <!-- bottom group mask --> <!--- @private --> <s:Group id="bottomGroupMask" includeIn="normalWithControlBar, disabledWithControlBar" left="1" right="1" top="1" bottom="1"> <!--- @private --> <s:Rect id="bottomMaskRect" left="0" right="0" top="0" bottom="0"> <s:fill> <s:SolidColor alpha="0"/> </s:fill> </s:Rect> </s:Group> <!-- layer 1: border --> <!--- @private --> <s:Rect id="border" left="0" right="0" top="0" bottom="0"> <s:stroke> <!--- @private --> <s:SolidColorStroke id="borderStroke" weight="1"/> </s:stroke> </s:Rect> <!-- layer 2: background fill --> <!--- Defines the appearance of the PanelSkin class's background. --> <s:Rect id="background" left="1" right="1" top="1" bottom="1"> <s:fill> <!--- @private Defines the PanelSkin class's background fill. The default color is 0xFFFFFF. --> <s:SolidColor id="backgroundFill" color="#FFFFFF"/> </s:fill> </s:Rect> <!-- layer 3: contents --> <!--- Contains the vertical stack of titlebar content and controlbar. --> <s:Group id="contents" left="1" right="1" top="1" bottom="1"> <s:layout> <s:VerticalLayout gap="0" horizontalAlign="justify"/> </s:layout> <!--- @private --> <s:Group id="topGroup" mask="{topGroupMask}"> <!-- layer 0: title bar fill --> <!--- @private --> <s:Rect id="tbFill" left="0" right="0" top="0" bottom="1"> <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="0xE2E2E2"/> <s:GradientEntry color="0xD9D9D9"/> </s:LinearGradient> </s:fill> </s:Rect> <!-- layer 1: title bar highlight --> <!--- @private --> <s:Rect id="tbHilite" left="0" right="0" top="0" bottom="0"> <s:stroke> <s:LinearGradientStroke rotation="90" weight="1"> <s:GradientEntry color="0xEAEAEA"/> <s:GradientEntry color="0xD9D9D9"/> </s:LinearGradientStroke> </s:stroke> </s:Rect> <!-- layer 2: title bar divider --> <!--- @private --> <s:Rect id="tbDiv" left="0" right="0" bottom="0" height="1"> <s:fill> <s:SolidColor color="0xC0C0C0"/> </s:fill> </s:Rect> <!-- layer 3: text --> <!--- @copy spark.components.Panel#titleDisplay --> <s:Label id="titleDisplay" left="9" right="3" top="1" bottom="0" minHeight="30" fontWeight="bold" maxDisplayedLines="1" textAlign="start" verticalAlign="middle"> </s:Label> </s:Group> <!-- Note: setting the minimum size to 0 here so that changes to the host component's size will not be thwarted by this skin part's minimum size. This is a compromise, more about it here: http://bugs.adobe.com/jira/browse/SDK-21143 --> <!--- @copy spark.components.SkinnableContainer#contentGroup --> <s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0"> </s:Group> <!--- @private --> <s:Group id="bottomGroup" includeIn="normalWithControlBar, disabledWithControlBar" minWidth="0" minHeight="0"> <s:Group left="0" right="0" top="0" bottom="0" mask="{bottomGroupMask}"> <!-- layer 0: control bar divider line --> <s:Rect left="0" right="0" top="0" height="1" alpha="0.22"> <s:fill> <s:SolidColor color="0x000000"/> </s:fill> </s:Rect> <!-- layer 1: control bar highlight --> <s:Rect left="0" right="0" top="1" bottom="0"> <s:stroke> <s:LinearGradientStroke rotation="90" weight="1"> <s:GradientEntry color="0xE5E5E5"/> <s:GradientEntry color="0xD8D8D8"/> </s:LinearGradientStroke> </s:stroke> </s:Rect> <!-- layer 2: control bar fill --> <s:Rect left="1" right="1" top="2" bottom="1"> <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="0xDADADA"/> <s:GradientEntry color="0xC5C5C5"/> </s:LinearGradient> </s:fill> </s:Rect> </s:Group> <!-- layer 3: control bar --> <!--- @copy spark.components.Panel#controlBarGroup --> <s:Group id="controlBarGroup" left="0" right="0" top="1" bottom="1" minWidth="0" minHeight="0"> <s:layout> <s:HorizontalLayout gap="10" paddingBottom="7" paddingLeft="10" paddingRight="10" paddingTop="7"/> </s:layout> </s:Group> </s:Group> </s:Group> <vicp:Adorner id="dragAdorner" right="1" bottom="1" rotation="180" visible="false"/> </s:Group> </s:SparkSkin>
AdornerSkin.mxml
<?xml version="1.0" encoding="utf-8"?> <s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <!-- host component --> <fx:Metadata> [HostComponent("net.myflex.vicp.Adorner")] </fx:Metadata> <s:Group top="0" bottom="0" left="0" right="0"> <s:Rect top="0" bottom="0" left="0" right="0"> <s:fill> <s:SolidColor color="0xffffff"/> </s:fill> </s:Rect> <s:Line top="0" left="0" height="10"> <s:stroke> <s:SolidColorStroke weight="2" color="0x123456"/> </s:stroke> </s:Line> <s:Line top="0" left="0" width="10"> <s:stroke> <s:SolidColorStroke weight="2" color="0x123456"/> </s:stroke> </s:Line> </s:Group> </s:Skin>
css
/* CSS file */ @namespace s "library://ns.adobe.com/flex/spark"; @namespace mx "library://ns.adobe.com/flex/mx"; @namespace vicp "net.myflex.vicp.*"; vicp|DragPanel{ skinClass:ClassReference("net.myflex.vicp.skins.DragPanelSkin"); } vicp|Adorner{ skinClass:ClassReference("net.myflex.vicp.skins.AdornerSkin") }