<?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" minWidth="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)" xmlns:layout="com.ichart.layout.*">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var dp:ArrayCollection=new ArrayCollection();
for (var i:int = 0; i < 32; i++)
{
var item:Object="按钮"+(i+1);
dp.addItem(item);
}
dataGroup.dataProvider=dp;
}
]]>
</fx:Script>
<fx:Declarations>
<s:ArrayCollection id="model">
<fx:String>This is text 1</fx:String>
<fx:String>This is text 2</fx:String>
<fx:String>This is text 3</fx:String>
<fx:String>This is text 4</fx:String>
<fx:String>This is text 5</fx:String>
<fx:String>This is text 6</fx:String>
<fx:String>This is text 7</fx:String>
<fx:String>This is text 8</fx:String>
<fx:String>This is text 9</fx:String>
<fx:String>This is text 10</fx:String>
<fx:String>This is text 11</fx:String>
<fx:String>This is text 12</fx:String>
<fx:String>This is text 12</fx:String>
<fx:String>This is text 13</fx:String>
<fx:String>This is text 14</fx:String>
<fx:String>This is text 15</fx:String>
<fx:String>This is text 16</fx:String>
<fx:String>This is text 17</fx:String>
<fx:String>This is text 18</fx:String>
<fx:String>This is text 19</fx:String>
<fx:String>This is text 20</fx:String>
<fx:String>This is text 21</fx:String>
</s:ArrayCollection>
</fx:Declarations>
<s:DataGroup id="dataGroup" width="{widthHslider.value}" height="{heightHslider.value}" x="10" y="10"
>
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="false"
>
<s:Button width="100" height="60" label="{data}"/>
<!--<s:Group id="group" top="0" bottom="0" left="0" right="0">
<s:Rect top="0" bottom="0" left="0" right="0">
<s:fill>
<s:SolidColor color="0xffffee"/>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="0x123456"/>
</s:stroke>
</s:Rect>
<s:BitmapImage source="{data}" horizontalCenter="0" verticalCenter="0"/>
<s:Label text="{data}" horizontalCenter="0" verticalCenter="0"/>
</s:Group>-->
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
<s:layout>
<layout:FlowLayout id="flowLayout" gap="{gapHslider.value}" />
</s:layout>
</s:DataGroup>
<s:Group width="{widthHslider.value}" height="{heightHslider.value}" x="8" y="8">
<s:Rect width="100%" height="100%">
<s:stroke>
<s:SolidColorStroke color="0"/>
</s:stroke>
</s:Rect>
</s:Group>
<s:Button label="向前" horizontalCenter="-35" verticalCenter="149" click="flowLayout.previous()"/>
<s:Button label="后退" horizontalCenter="40" verticalCenter="149" click="flowLayout.next()" />
<s:HSlider id="widthHslider" x="356" y="311" maximum="1200" minimum="100" value="204" stepSize="2"/>
<s:HSlider id="heightHslider" x="356" y="331" maximum="280" minimum="60" value="244" stepSize="2"/>
<s:HSlider id="gapHslider" x="356" y="351" maximum="20" minimum="0" value="10" stepSize="1"/>
</s:Application>
package com.ichart.layout
{
/**
*
* 作者 黄记新, 2011-11-22
*/
import flash.display.DisplayObject;
import gs.TweenLite;
import gs.easing.Quad;
import mx.core.ILayoutElement;
import spark.components.supportClasses.GroupBase;
import spark.layouts.supportClasses.LayoutBase;
public class FlowLayout extends LayoutBase
{
private var _currentPage:int=1;
private var _requestedPage:Number = 1;
private var _titalPage:int=1;
private var _gap:Number=0;
private var _isAnimating:Boolean = false;
private var _animationDuration:Number = 1;
private var _useAnimation:Boolean = true;
public function get easingFunction():Function
{
return _easingFunction;
}
public function set easingFunction(value:Function):void
{
_easingFunction = value;
}
private var _easingFunction:Function = Quad.easeOut;
private var _easingType:String = EASING_DEFAULT;
private var switchIt:Boolean = false;
[Bindable]
public static var EASING_BOUNCE:String = "bounce";
[Bindable]
public static var EASING_ELASTIC:String = "elastic";
[Bindable]
public static var EASING_DEFAULT:String = "";
[Bindable]
public static var EASING_CUBIC:String = "cubic";
public function FlowLayout()
{
super();
this.clipAndEnableScrolling=true;
}
/**
* 请求页数;
*/
[Bindable]
public function get requestedPage():Number
{
return _requestedPage;
}
public function set requestedPage(value:Number):void
{
_requestedPage = value;
}
[Bindable]
public function get useAnimation():Boolean
{
return _useAnimation;
}
public function set useAnimation(value:Boolean):void
{
_useAnimation = value;
}
[Bindable]
public function get animationDuration():Number
{
return _animationDuration;
}
public function set animationDuration(value:Number):void
{
_animationDuration = value;
}
[Bindable]
public function get isAnimating():Boolean
{
return _isAnimating;
}
public function set isAnimating(value:Boolean):void
{
_isAnimating = value;
}
[Bindable]
public function get gap():Number
{
return _gap;
}
public function set gap(value:Number):void
{
if(_gap == value){
return;
}
_gap = value;
if(target)
this.target.invalidateDisplayList();
}
/**
* 当前页数;
*/
public function get currentPage():int
{
return _currentPage;
}
/**
* @private
*/
public function set currentPage(value:int):void
{
_currentPage = value;
}
/**
* 总页数;
*/
[Bindable]
public function get titalPage():int
{
return _titalPage;
}
/**
* @private
*/
public function set titalPage(value:int):void
{
_titalPage = value;
}
/**
* 移到下一页;
*
*/
public function next():void
{
if(this.isAnimating)
{
return;
}
updatePagesNumber();
if(this.currentPage + 1 > this.titalPage) //动画部分;
{
this.requestedPage = 1;
switchIt = true;
}else{
this.requestedPage++;
}
/*if(this.currentPage + 1 > this.titalPage) //无动画部分;
{
this.currentPage = 1;
}else{
this.currentPage++;
}*/
//刷新页面;
var layoutTarget:GroupBase = target;
if (!layoutTarget)
return;
layoutTarget.invalidateDisplayList();
}
// 移到前一页;
public function previous():void
{
if(this.isAnimating)
{
return;
}
updatePagesNumber();
if(this.currentPage - 1 == 0) //动画部分;
{
this.requestedPage = this.titalPage;
switchIt = true;
}else{
this.requestedPage--;
}
/*if(this.currentPage - 1 == 0) //无动画部分;
{
this.currentPage = this.titalPage;
}else{
this.currentPage--;
}*/
//刷新页面;
var layoutTarget:GroupBase = target;
if (!layoutTarget)
return;
layoutTarget.invalidateDisplayList();
}
/**
*
* @param switchDirection
*
*/
private function animatePages(switchDirection:Boolean=false):void
{
var layoutTarget:GroupBase = target;
if (!layoutTarget)
return;
this.isAnimating = true;
var offsetMultiplier:Number;
if(this.requestedPage > this.currentPage)
{
offsetMultiplier = -1;
}else{
offsetMultiplier = 1;
}
if(switchIt)
{
offsetMultiplier *= -1;
}
var offset:Number = layoutTarget.width * offsetMultiplier;
createPage(this.currentPage);
createPage(this.requestedPage, offset, false);
var element:ILayoutElement;
for (var index:int = 0; index < target.numElements; index++)
{
element = target.getElementAt(index);
if( !element.includeInLayout )
continue;
if(isElementOnPage(element, this.currentPage) || isElementOnPage(element, this.requestedPage))
{
TweenLite.to(DisplayObject(element), this.animationDuration, {x: DisplayObject(element).x + (offset), ease: this.easingFunction});
}
}
TweenLite.delayedCall(this.animationDuration, animationDone);
}
private function animationDone():void
{
this.isAnimating = false;
this.currentPage = this.requestedPage;
}
/**
* 针对宽度可能带来的变化,更新总页数等;
*
*/
private function updatePagesNumber():void
{
var layoutTarget:GroupBase = target;
if (!layoutTarget)
return;
var pageCount:Number = 1;
var tempX:Number=0;
var tempY:Number=0;
for (var i:int = 0; i < layoutTarget.numElements; i++)
{
var element:ILayoutElement=layoutTarget.getElementAt(i);
element.setLayoutBoundsSize(NaN,NaN);
if( !element.includeInLayout )
continue;
var elementWidth:Number=element.getLayoutBoundsWidth();
var elementHeight:Number=element.getLayoutBoundsHeight();
var tempHeight:Number=tempY+elementHeight+gap;
if(tempHeight>layoutTarget.height){
tempY=elementHeight+gap;
tempX+=elementWidth+gap;
}else{
tempY+=elementHeight+gap;
}
if(tempX+elementWidth>layoutTarget.width){
pageCount++;
tempX=0;
}
}
this.titalPage=pageCount;
}
/**
* 复写布局函数,对元素进行新的排列;
* @param unscaledWidth
* @param unscaledHeight
*
*/
override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
var layoutTarget:GroupBase=this.target;
if(!layoutTarget){
return;
}
updatePagesNumber();
if(titalPage<1){
return;
}
// createPage(this.currentPage);
if(this.requestedPage!=this.currentPage && this.useAnimation){
if(!this.isAnimating ){
animatePages(switchIt);
switchIt = false;
}
}else{
createPage(this.currentPage);
}
}
/**
* 该方法将元素移到它们该到的位置;
* @param pageNum
* @param offset
* @param hideItems
*
*/
private function createPage(pageNum:int,offset:Number=0,hideItems:Boolean=true):void
{
if(pageNum > this.titalPage)
{
pageNum = this.titalPage;
this.currentPage = pageNum;
}
var layoutTarget:GroupBase=this.target;
if(!layoutTarget)
{
return;
}
var element:ILayoutElement;
var tempX:Number=0;
var tempY:Number=0;
for (var index:int = 0; index < target.numElements; index++)
{
element = target.getElementAt(index);
if( !element.includeInLayout )
continue;
var elementWidth:Number=element.getLayoutBoundsWidth();
var elementHeight:Number=element.getLayoutBoundsHeight();
if(!isElementOnPage(element, pageNum))
{
if(hideItems)
{
DisplayObject(element).visible = false;
}
continue;
}else
{
DisplayObject(element).visible = true;
if(tempY+elementHeight+gap>=layoutTarget.height){
tempY=0;
tempX+=elementWidth+gap;
}
element.setLayoutBoundsPosition(tempX-offset,tempY);
tempY+=elementHeight+gap;
}
}
}
/**
* 根据元素和页码数判断元素是否在所在页码数上面;
* @param element
* @param pageNum
* @return
*
*/
private function isElementOnPage(layoutElement:ILayoutElement, pageNum:int):Boolean
{
var layoutTarget:GroupBase = target;
if (!layoutTarget)
return false;
var element:ILayoutElement;
var tempX:Number=0;
var tempY:Number=0;
var pageCount:Number = 1;
for (var index:int = 0; index < target.numElements; index++)
{
element = target.getElementAt(index);
var elementWidth:Number=element.getLayoutBoundsWidth();
var elementHeight:Number=element.getLayoutBoundsHeight();
if( !element.includeInLayout )
continue;
if(tempY+elementHeight+gap>=layoutTarget.height){
tempY=elementHeight+gap;
tempX+=elementWidth+gap;
}else{
tempY+=elementHeight+gap;
}
if(tempX+elementWidth>layoutTarget.width){
pageCount++;
tempX=0;
}
if(layoutElement==element)
return pageNum==pageCount;
}
return false;
}
}
}