Problem Summary: In a flex project, I need to insert an object to a object list which is derived from Container component. However, the list has fixed width and height, and the items of the list are too many to display one-time. So i have to scroll the list to the proper position then drag the object from a panel and insert it. I need a convenient way to complete this. I worte an AutoScrollManager utility to help myself.
Solution Summary: I add an event listener to the stage object of container’s systemManager object. It’s used to find the proper Container during the run-time because the container cannot trigger the MouseMove event while I am dragging the object from the panel. It is covered by what I am dragging. I have to find the proper container according to the Mouse coordinates. The function findContainer helps me a lot. Despite of this big problem, there is nothing hard to deal with.
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript> </script> <script> window.google_render_ad(); </script>
Demo(Download Full Project):
Press the left button of your mouse and do not release it. Move your mouse pointer inside the panel arbitrary. When the pointer moves around the texts, the scroll-bars scroll automatically.
Description: The AutoScrollManager provide two static functions to enable or disable auto-scrolling, addAutoScroll and removeAutoScroll, you should pass the target Container component to these functions. With the addAutoScroll function, there are another two parameters: scrollSpeed and bound. scrollSpeed determine the speed the scroll-bars scrolling. The bound is based on the model below:
viewMetrics is defined by the container self. Detailed info you will find in the flex SDK document.
* Returns an object that has four properties: <code>left</code>,
* <code>top</code>, <code>right</code>, and <code>bottom</code>.
* The value of each property equals the thickness of the chrome
* (visual elements) around the edge of the container.
Scroll bars appear when they are required.
Bound is defined by user. It is used to specify a particular area where the scroll bars scrolling automatically while the mouse is moving in it.
In this AutoScrollManger class , when the mouse is moving in the area of viewMetrics or Bound, the scroll bars scroll.
Codes:
- <?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Application
- xmlns:mx=”http://www.adobe.com/2006/mxml”
- layout=”absolute”
- xmlns:local=”*”
- height=”200″
- width=”200″
- creationComplete=”initApp();”>
- <mx:XML id=”myData” xmlns="">
- <root>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl”/>
- </root>
- </mx:XML>
- <mx:Script>
- <![CDATA[
- private function initApp():void
- {
- AutoScrollingManager.addAutoScroll(myPan);
- }
- ]]>
- </mx:Script>
- <mx:Panel id=”myPan” width=”{application.width}” height=”{application.height}”>
- <mx:VBox width=”100%” height=”100%”>
- <mx:Repeater id=”myRep” dataProvider=”{myData.item}”>
- <mx:Label text=”{myRep.currentItem.@name}”/>
- </mx:Repeater>
- </mx:VBox>
- </mx:Panel>
- </mx:Application>
Following is AutoScrollManager Class:
- import flash.display.Stage;
- import flash.events.Event;
- import flash.events.MouseEvent;
- import flash.geom.Point;
- import flash.utils.Dictionary;
- import mx.core.Container;
- import mx.core.EdgeMetrics;
- public class AutoScrollingManager
- {
- private static var managers:Dictionary = new Dictionary();
- public var scrollSpeed:int = 10;
- public var scrollFunction:Function = horizontalScroll;
- private var _bound:EdgeMetrics;
- public var bound:EdgeMetrics = new EdgeMetrics(20,20,20,20);
- public static function addAutoScroll(container:Container,scrollSpeed:int = 10,bound:EdgeMetrics = null):void
- {
- var manager:AutoScrollingManager = new AutoScrollingManager();
- manager.scrollSpeed = scrollSpeed;
- if(bound)manager.bound = bound;
- managers[container] = manager;
- container.systemManager.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
- container.systemManager.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
- }
- public static function removeAutoScroll(container:Container):void
- {
- container.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
- container.systemManager.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
- if(managers[container])
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,managers[container].scrollFunction);
- managers[container] = null;
- }
- }
- private static function onMouseMove(event:MouseEvent):void
- {
- var pt:Point = new Point(event.localX,event.localY);
- var container:Container = findContainer(pt,event.currentTarget.stage);
- if(!container)
- return;
- var manager:AutoScrollingManager = managers[container];
- if(!event.buttonDown)
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- return;
- }
- var vm:EdgeMetrics = container.viewMetrics;
- var _bound:EdgeMetrics = new EdgeMetrics();
- _bound.bottom = manager.bound.bottom;
- _bound.left = manager.bound.left;
- _bound.right = manager.bound.right;
- _bound.top = manager.bound.top;
- if(container.horizontalScrollBar)_bound.bottom += container.horizontalScrollBar.height;
- if(container.verticalScrollBar)_bound.right += container.verticalScrollBar.width;
- if(vm.bottom!=0) _bound.bottom += vm.bottom;
- if(vm.left!=0) _bound.left += vm.left;
- if(vm.right!=0) _bound.right += vm.right;
- if(vm.top!=0) _bound.top += vm.top;
- pt = event.target.localToGlobal(pt);
- pt = container.globalToLocal(pt);
- var insideLeftTopCorner:Boolean;
- var insideLeftBottomCorner:Boolean ;
- var insideRightTopCorner:Boolean;
- var insideRightBottomCorner:Boolean ;
- insideLeftTopCorner = pt.x < _bound.left && pt.y < _bound.top;
- insideLeftBottomCorner = pt.x < _bound.left && pt.y > container.height - _bound.bottom;
- insideRightTopCorner = pt.x > container.width - _bound.right && pt.y < _bound.top;
- insideRightBottomCorner = pt.x > container.width - _bound.right&& pt.y > container.height - _bound.bottom;
- if(insideLeftTopCorner||insideLeftBottomCorner||insideRightTopCorner||insideRightBottomCorner)
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- return;
- }
- if(container.horizontalScrollBar)
- {
- if(pt.y > container.height - container.horizontalScrollBar.height - vm.bottom)
- {
- return;
- }
- manager.scrollFunction = horizontalScroll;
- if(pt.x < _bound.left)
- {
- if( container.horizontalScrollPosition!=0)
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- manager.scrollSpeed = Math.abs(manager.scrollSpeed)*-1;
- }
- }
- else if((pt.x > container.width-_bound.right && pt.x < container.width - (container.verticalScrollBar?container.verticalScrollBar.width:0) - vm.right) || pt.x > container.width - vm.right)
- {
- if(container.horizontalScrollPosition!=container.maxHorizontalScrollPosition)
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- manager.scrollSpeed = Math.abs(manager.scrollSpeed);
- }
- }
- else
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- }
- }
- if(container.verticalScrollBar)
- {
- if(pt.x > container.width - container.verticalScrollBar.width - vm.right)
- {
- return;
- }
- manager.scrollFunction = verticalScroll;
- if(pt.y < _bound.top)
- {
- if(container.verticalScrollPosition!=0)
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- manager.scrollSpeed = Math.abs(manager.scrollSpeed)*-1;
- }
- }
- else if((pt.y > container.height - _bound.bottom && pt.y < container.height - (container.horizontalScrollBar?container.horizontalScrollBar.height:0) - vm.bottom) || pt.y > container.height - vm.bottom)
- {
- if(container.verticalScrollPosition!=container.maxVerticalScrollPosition)
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- manager.scrollSpeed = Math.abs(manager.scrollSpeed);
- }
- }
- else
- {
- container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
- }
- }
- }
- private static function onMouseUp(event:MouseEvent):void
- {
- event.currentTarget.removeEventListener(Event.ENTER_FRAME,horizontalScroll);
- event.currentTarget.removeEventListener(Event.ENTER_FRAME,verticalScroll);
- }
- private static function horizontalScroll(event:Event):void
- {
- var pt:Point = new Point(event.currentTarget.stage.mouseX,event.currentTarget.stage.mouseY);
- var container:Container = findContainer(pt,event.currentTarget.stage);
- if(!container)
- return;
- container.horizontalScrollPosition += managers[container].scrollSpeed;
- }
- private static function verticalScroll(event:Event):void
- {
- var pt:Point = new Point(event.currentTarget.stage.mouseX,event.currentTarget.stage.mouseY);
- var container:Container = findContainer(pt,event.currentTarget.stage);
- if(!container)
- return;
- container.verticalScrollPosition += managers[container].scrollSpeed;
- }
- private static function findContainer(pt:Point,stage:Stage):Container
- {
- var objects:Array = stage.getObjectsUnderPoint(pt);
- for each(var object:Object in objects)
- {
- var result:Object = doFind(object);
- if(result!=null)
- {
- return Container(result);
- }
- }
- return null;
- }
- private static function doFind(object:Object):Container
- {
- if(object.parent && object.parent is Container)
- {
- if(managers[object.parent] != null)
- {
- return object.parent;
- }
- else
- {
- return doFind(object.parent);
- }
- }
- return null;
- }
- }