Flex/ActionScript Making Complex UIComponents Draggable

Adobe Flex makes it really easy to enable dragging for your UIComponents.  For example, if you have a spark BorderContainer you simply assign mouse listeners to it and then use the startDrag() and stopDrag() methods. What gets tricky is when you have TextInput, or TextArea boxes or other user accessible content inside the component and you don’t want the entire container to drag around when the user clicks on them.

The easiest way I know to prevent this annoying bug from happening is to listen on the MouseEvent for the event target type, and then use that to determine what course of action you want to take. In my case, since I’m using a BorderContainer I listen on the MouseEvent then use the getQualifiedClassName() method to look for the class name string called “spark.skins.spark::BorderContainerSkin”. That way the drag functionality will only be enabled when the user clicks directly on the container. If they click on a text field, then the event.target will be different and the component won’t be draggable!

protected function routeDirectionsContainer_mouseDownHandler(event:MouseEvent):void
{
	//Only allow dragging if user clicks on the parent container rather than the text fields.
	var className:String = flash.utils.getQualifiedClassName( event.target );
	if(className == "spark.skins.spark::BorderContainerSkin")
	{
		routeDirectionsContainer.startDrag(false,null);
	}

protected function routeDirectionsContainer_mouseUpHandler(event:MouseEvent):void
{
	routeDirectionsContainer.stopDrag();
}

The event target property tells you exactly what the user has clicked on. By intercepting that information you can precisely tune what happens in your user interface components. If you don’t know how to get this information, set a debug point on the method that receives the MouseEvent and then inspect the string that is returned by the getQualifiedClassName() method.

Just for reference here’s how to drag enable a UIComponent:

<!-- Note: includes mouseOut listener for mobile. -->
<s:BorderContainer id="routeDirectionsContainer"
	mouseDown="routeDirectionsContainer_mouseDownHandler(event)"
	mouseUp="routeDirectionsContainer_mouseUpHandler(event)"
	mouseOut="routeDirectionsContainer_mouseUpHandler(event)">

	<s:TextInput id="fromText" text="380 New York St, Redlands, CA, 92373"/>
	<s:TextInput id="toText" text="300 Main St., Santa Monica, CA"/>

</s:BorderContainer>