GHOST CAT
准备工作 <ul><li>创建工程 </li></ul><ul><li>导入 Ghost Cat SWC 文件 </li></ul><ul><li>创建资源 FLA 文件 asset.fla </li></ul><ul><li>创建多语言配置文...
asset.fla <ul><li>内容如图所示 </li></ul>其中 upArrow,downArrow 元件位于 scrollBar 元件中, nameText,numText 位于 render 元件中。所示文字表示的是元件在场景中的...
UI.lang <ul><li>多语言并不是必须的,只是这个例子中包含了此特性。在之后的代码会会自动转换。 </li></ul><ul><li>内容只有两行 </li></ul><ul><li>name= 新的文字 </li></ul><ul>...
建立文档类 <ul><li>public   class  test  extends  Sprite </li></ul><ul><li>{ </li></ul><ul><li>public   function  test() </li><...
Panel.as ( 效果 ) <ul><li>public   class  Panel  extends   GBuilderBase  // 继承此类便有拥有全部特性 </li></ul><ul><li>{ </li></ul><ul><...
Panel.as v2 ( 效果 ) <ul><li>public   class  Panel  extends  GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public   var...
Render.as <ul><li>public   class  Render  extends  GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public   var  nameTe...
已经有基类,不能直接使用 GBuildBase? <ul><li>public   class  Render  extends  GButton </li></ul><ul><li>{ </li></ul><ul><li>public   v...
关于队列 先看看需求
需求分析 <ul><li>先移动列表,然后修改数据,最后将列表移回原来的位置。 (因为数据不会立即生效,因此需要缓存在变量中) </li></ul><ul><li>更改数据后列表长度可能变化,所以需要将滚动重置。 </li></ul><ul><...
是否打算这样去做? <ul><li>private   var  temp:Array; </li></ul><ul><li>public   function  setData(v:Array): void </li></ul><ul><li...
另一种写法 <ul><li>public   function  setData( v :Array): void </li></ul><ul><li>{ </li></ul><ul><li>var  list:Array = [ </li><...
Oper 类 <ul><li>上面的代码是先创建了一个数组,数组里面都是一些继承于 Oper 的类,每个对象表示着一个具体操作。这个对象创建出来并不会立即执行,而要使用对象的 execute 方法来启动。 </li></ul><ul><li>创...
Queue <ul><li>这是一个特殊的 Oper ,参数是一个数组包含着其他的 Oper 对象。执行它将会顺序执行所有子对象。 </li></ul><ul><li>就像这样:  new  Queue(list).execute(); </l...
SetPropertyOper <ul><li>SetPropertyOper( this .tabBar,{mouseEnabled: false ,mouseChildren: false }), </li></ul><ul><li>这个类...
TweenOper <ul><li>TweenOper( this .render,500,{y:300,ease:Circ.easeIn}) </li></ul><ul><li>和 Tween 参数相似,只不过实例化这个对象并不会马上执行 T...
FunctionOper <ul><li>FunctionOper( this .scrollBar.resetContent,[true,false]) </li></ul><ul><li>这个类非常简单,就是执行一个函数,第二个参数是参数数...
…… <ul><li>除此之外还有很多 </li></ul><ul><li>但更重要的是,你可以自己创建一个 Oper 的派生类,便可以和其他类放置在同一个队列中执行 </li></ul>
一个简单的例子(设置发光提示点击某个对象,点击后继续执行) <ul><li>public   class  ClickOper  extends  Oper </li></ul><ul><li>{ </li></ul><ul><ul><li>p...
GListBase 列表类
刚才示例的代码,只是将 tabBar 的类型由 Gbutton 改成了 GListBase <ul><li>public   class  Panel  extends  GBuilderBase </li></ul><ul><li>{ </l...
<ul><li>GListBase 只负责复制子对象实现列表效果,它没有自己的大小概念,也没有滚动条。 </li></ul><ul><li>它可以像列表那样加上滚动条使用,也可以像上面那样直接作为 TabBar 存在。 </li></ul><u...
列表项的数量可以达到 1W <ul><li>GListBase 已经实现了对象池,只有显示出的子对象才会被实例化。因此显示 1W (或者更多)和显示 2 个消耗的资源是相同的。 </li></ul><ul><li>上面的例子中的第 2 个 Ta...
GMovieClip 动画扩展类
其实之前的例子已经出现了一次 <ul><li>public var mc:GMovieClip; </li></ul><ul><li>public   function  Panel() </li></ul><ul><li>{ </li></u...
GMovieClip 关键属性 / 方法 <ul><li>frameRate  可以设置动画的播放帧频,当值为负时即为倒放,默认为舞台帧频 </li></ul><ul><li>frameRate 的播放控制是基于时间的,因此并不会因为 CPU ...
GMovieClip 关键属性 / 方法 <ul><li>setLabel( 帧标签,播放次数 ) </li></ul><ul><li>帧标签就是 FLASH 时间线上对帧的命名,播放次数为 -1 时为无限循环(默认值) </li></ul><...
<ul><li>如果你的动画帧被命名分割为三个区域 : start ,  loop , end ,然后你希望先播放 start ,然后重复播放 loop 三次,最后播放完 end 然后停止,代码如下 </li></ul><ul><li>setL...
<ul><li>queueDestory() </li></ul><ul><li>新版本增加的方法,执行它后会在动画播放完毕后自动移除自己。于是不需要再去监听 MOVIE_EMPTY 事件了。毕竟这个需求就和动画仅播放一次一样常见…… </li...
并不只是矢量 <ul><li>GBitmapMovieClip 和它拥有几乎完全相同的属性和方法,但它所支持的是位图序列。 </li></ul><ul><li>与 MovieClip 不同,它的构造函数参数是一个由 BitmapData 组成的...
<ul><li>第二个参数并不是必须的。但如果想使用 queueLabel 这类方法的话,没有帧标签该如何操作?虽然,你也可以直接手动设置 currentFrame </li></ul><ul><li>你可以自己手动创建这个 FrameLabe...
一个 GBitmapMovieClip 的实例 <ul><li>只贴出相关部分( BitmapSeparateUtil , FrameLabelUtil 也是库中的类 ) </li></ul><ul><li>var  source:Array ...
动画缓存? <ul><li>矢量动画太复杂,播放不顺畅?这时候只能缓存。但具体应当如何去做呢? </li></ul><ul><li>当矢量和位图动画拥有同样的方法的时候,缓存动画就很简单了。下面的代码最后都能生成一个 GBitmapMovieC...
SelectGroup& ViewStack 关于页面切换
asset.fla <ul><li>同理, tabBar 和 viewStack 元件类分别包含着 tab1,tab2,tab3 以及 render1,render2,render3 </li></ul><ul><li>整个元件链接了类名 as...
Panel.as v4  ( 效果 ) <ul><li>public   class  Panel  extends  GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public   va...
ZoomButton.as <ul><li>public   class  ZoomButton  extends  GButton </li></ul><ul><li>{ </li></ul><ul><li>public   function...
SelectGroup <ul><li>// 按钮条 </li></ul><ul><li>selectGroup =  new  SelectGroup([ tab1,tab2,tab3 ], true ); </li></ul><ul><li...
GViewState <ul><li>此对象会将自己的 Children 当作多个 State 来处理,同时只显示其中的一个 </li></ul><ul><li>ViewState 主要的特性是提供了 showFromRight,showFro...
Layout 布局
当你并不需要动态布局的时候 <ul><li>可以在生成界面之后手动设置 UI 的各个属性,如果有些数组无法简单的少量代码写出来的话,可以使用 LayoutUtil 静态类。 </li></ul><ul><li>对齐  LayoutUtil.si...
当你需要动态布局的时候 <ul><li>使用 Layout 系列对象,将容器作为参数传入,并设置必要的属性(方向,边距,间距等),当容器的子对象都是 GBase 对象时即可自动布局 </li></ul><ul><li>AbsoluteLayou...
编写自己的 Layout <ul><li>重写 Layout.as 的 layoutChildren 方法即可 </li></ul><ul><li>protected   override   function  layoutChildren(...
当你希望容器本身也能根据子对象来决定自己大小的时候 <ul><li>Layout 对象需要实现 measureChildren 方法,最后通过执行 super .measureChildren(width,height) 来决定新的宽高 </l...
GView <ul><li>GBox,GHBox,GVBox 已经默认包含了 LinearLayout 对象,因此只需要普通的 addChild 便能自动布局 </li></ul><ul><li>任何时候都可以重新执行 setLayout 来指...
例:给刚才的例子加上布局功能 ( 效果 ) <ul><li>public   var  tab1:ZoomButton; </li></ul><ul><li>public   var  tab2:ZoomButton; </li></ul><u...
Upcoming SlideShare
Loading in …5
×

Ghost cat 以皮肤为主体的ui框架(唐翎)

2,555 views
2,448 views

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,555
On SlideShare
0
From Embeds
0
Number of Embeds
134
Actions
Shares
0
Downloads
41
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Ghost cat 以皮肤为主体的ui框架(唐翎)

  1. 1. GHOST CAT
  2. 2. 准备工作 <ul><li>创建工程 </li></ul><ul><li>导入 Ghost Cat SWC 文件 </li></ul><ul><li>创建资源 FLA 文件 asset.fla </li></ul><ul><li>创建多语言配置文件 ui.lang (可选) </li></ul>
  3. 3. asset.fla <ul><li>内容如图所示 </li></ul>其中 upArrow,downArrow 元件位于 scrollBar 元件中, nameText,numText 位于 render 元件中。所示文字表示的是元件在场景中的示例名。 整个图形绑定了类名 asset.Panel (此外, tabBar 和 render 由于在之后会被复制,也绑定了类名 asset.TabBar,asset.Render ,但这个类名只是用于复制,代码中并不会出现,其实无论取什么名字都没有关系)
  4. 4. UI.lang <ul><li>多语言并不是必须的,只是这个例子中包含了此特性。在之后的代码会会自动转换。 </li></ul><ul><li>内容只有两行 </li></ul><ul><li>name= 新的文字 </li></ul><ul><li>title= 标题栏 </li></ul><ul><li>在后面的代码中, @name 会被自动转换为“ 新的文字 ”, @title 会被自动转换为“ 标题栏 ”,将不再进行解释 </li></ul>
  5. 5. 建立文档类 <ul><li>public class test extends Sprite </li></ul><ul><li>{ </li></ul><ul><li>public function test() </li></ul><ul><li>{ </li></ul><ul><li>LanguageManager.instance.load( &quot; ui.lang &quot; ); // 加载多语言 </li></ul><ul><li>AssetManager.instance.loadResource( &quot; asset.swf &quot; ); // 加载资源 </li></ul><ul><li>Queue.defaultQueue.addEventListener(OperationEvent.OPERATION_COMPLETE,loadCompleteHandler);// 监听资源加载完成事件 </li></ul><ul><li>} </li></ul><ul><li>private function loadCompleteHandler(event:OperationEvent): void </li></ul><ul><li>{ </li></ul><ul><li>stage.addChild(new ToolTipSprite());// 加入提示框 </li></ul><ul><li>addChild( new Panel ());// 显示 Panel 窗体 </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  6. 6. Panel.as ( 效果 ) <ul><li>public class Panel extends GBuilderBase // 继承此类便有拥有全部特性 </li></ul><ul><li>{ </li></ul><ul><li>public var titleText:GText; </li></ul><ul><li>public var mc:GMovieClip; </li></ul><ul><li>public var tabBar:GButton; </li></ul><ul><li>public var upArrow:GButton; </li></ul><ul><li>public var downArrow:GButton; </li></ul><ul><li>public var nameText:GText; </li></ul><ul><li>public var numText:GText; </li></ul><ul><li>public function Panel() </li></ul><ul><li>{ </li></ul><ul><li>super ( &quot; asset.Panel &quot; ); // 连接资源 </li></ul><ul><li>tabBar.data = &quot;A&quot; ; </li></ul><ul><li>nameText.text = &quot;@name&quot; ; </li></ul><ul><li>numText.text = &quot;A&quot; ; </li></ul><ul><li>mc.setLabel( null ,1); // 让动画只播放一次 </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>类名 asset.Panel 资源和类属性名称一一对应
  7. 7. Panel.as v2 ( 效果 ) <ul><li>public class Panel extends GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public var titleText:GText; </li></ul><ul><li>public var mc:GMovieClip; </li></ul><ul><li>public var tabBar:GButton; </li></ul><ul><li>//public var upArrow:GButton; </li></ul><ul><li>//public var downArrow:GButton; </li></ul><ul><li>public var scrollBar :GHScrollBar; </li></ul><ul><li>//public var nameText:GText; </li></ul><ul><li>//public var numText:GText; </li></ul><ul><li>public var render :GListBase; </li></ul><ul><li>public function Panel() </li></ul><ul><li>{ </li></ul><ul><li>super ( “asset.Panel” );// 仍然使用原来的资源 </li></ul><ul><li>mc.setLabel( null ,1); // 让动画只播放一次 </li></ul><ul><li>tabBar.data = &quot;GhostCat&quot; ; </li></ul><ul><li>render.type = UIConst.HORIZONTAL; // 设置 List 方向 </li></ul><ul><li>render.itemRender = Render ; // 设置 Render </li></ul><ul><li>render.data = [ &quot;G&quot; , &quot;H&quot; , &quot;O&quot; , &quot;S&quot; , &quot;T&quot; , &quot; &quot; , &quot;C&quot; , &quot;A&quot; , &quot;T&quot; ]; </li></ul><ul><li>scrollBar.setTarget(render,render.columnWidth * 2); // 指定滚动条 </li></ul><ul><li>scrollBar.detra = render.columnWidth; // 指定滚动距离 </li></ul><ul><li>new ZoomEffect( this , null ,0.1,1000,{ease:Elastic.easeIn}, true ).execute();// 展开效果 </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>这里直接定义父层元件,滚动条的两个按钮自动声明,而 render 则在 Render.as 中定义 设置列表的伸展方向,渲染器 ( 见下页,内容,设置滚动区域,滚动速度 最后加入一个从中间展开的效果
  8. 8. Render.as <ul><li>public class Render extends GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public var nameText:GText; </li></ul><ul><li>public var numText:GText; </li></ul><ul><li>public function Render(skin:*= null , replace:Boolean= true ) </li></ul><ul><li>{ </li></ul><ul><ul><li>super (skin, replace);// 保持默认值,皮肤由外部传入 </li></ul></ul><ul><li>} </li></ul><ul><li> // 复写 data 的 set 方法来获得数据 </li></ul><ul><li>public override function set data(v:*) : void </li></ul><ul><li>{ </li></ul><ul><ul><li>super .data = v; </li></ul></ul><ul><ul><li>nameText.text = numText.text = v; </li></ul></ul><ul><ul><li>this .toolTip = &quot; 当前值: &quot; + v; </li></ul></ul><ul><ul><li>TextFieldUtil.autoFontSize(numText.textField); // 调整字号使得可以全部显示 </li></ul></ul><ul><li>} </li></ul><ul><li> // 复写 selected 属性来设置选中效果 </li></ul><ul><li>public override function set selected(v:Boolean) : void </li></ul><ul><li>{ </li></ul><ul><ul><li>super .selected = v; </li></ul></ul><ul><ul><li>this .transform.colorTransform = v ? new ColorTransform(1,1,1,1,50,50,50) : new ColorTransform(); </li></ul></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  9. 9. 已经有基类,不能直接使用 GBuildBase? <ul><li>public class Render extends GButton </li></ul><ul><li>{ </li></ul><ul><li>public var nameText:GText; </li></ul><ul><li>public var numText:GText; </li></ul><ul><li>public function Render(skin:*= null , replace:Boolean= true ) </li></ul><ul><li>{ </li></ul><ul><li>super (skin, replace); </li></ul><ul><li>UIBuilder.buildAll( this ); </li></ul><ul><li>} </li></ul><ul><li>public override function destory(): void </li></ul><ul><li>{ </li></ul><ul><li>UIBuilder.destory( this ); </li></ul><ul><li>super .destory(); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>public class Render extends GButton </li></ul><ul><li>{ </li></ul><ul><li>public var nameText:GText; </li></ul><ul><li>public var numText:GText; </li></ul><ul><li>public function Render(skin:*= null , replace:Boolean= true ) </li></ul><ul><li>{ </li></ul><ul><li>super (skin, replace); </li></ul><ul><li>nameText = new GText( this .content[ &quot;nameText&quot; ]); </li></ul><ul><li>numText = new GText( this .content[ &quot;numText&quot; ]); </li></ul><ul><li>} </li></ul><ul><li>public override function destory(): void </li></ul><ul><li>{ </li></ul><ul><li>nameText.destory(); </li></ul><ul><li>numText.destory(); </li></ul><ul><li>super .destory(); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  10. 10. 关于队列 先看看需求
  11. 11. 需求分析 <ul><li>先移动列表,然后修改数据,最后将列表移回原来的位置。 (因为数据不会立即生效,因此需要缓存在变量中) </li></ul><ul><li>更改数据后列表长度可能变化,所以需要将滚动重置。 </li></ul><ul><li>重复执行这段代码会有各种问题,因此移动过程中按钮应当是禁用的。 </li></ul>
  12. 12. 是否打算这样去做? <ul><li>private var temp:Array; </li></ul><ul><li>public function setData(v:Array): void </li></ul><ul><li>{ </li></ul><ul><ul><li>temp = v; </li></ul></ul><ul><ul><li>tabBar.mouseEnabled = tabBar.mouseChildren = false ; </li></ul></ul><ul><ul><li>TweenUtil.to( this .render,500,{y:300,ease:Circ.easeIn,onComplete:tween1CompleteHandler}); </li></ul></ul><ul><li>} </li></ul><ul><li>private function tween1CompleteHandler(): void </li></ul><ul><li>{ </li></ul><ul><ul><li>this .render.data = temp; </li></ul></ul><ul><ul><li>temp = null ; </li></ul></ul><ul><ul><li>this .scrollBar.resetContent( true , false );// 重置滚动条 </li></ul></ul><ul><ul><li>TweenUtil.to( this .render,500,{y:0,ease:Circ.easeOut,onComplete:tween2CompleteHandler}); </li></ul></ul><ul><li>} </li></ul><ul><li>private function tween2CompleteHandler(): void </li></ul><ul><li>{ </li></ul><ul><ul><li>tabBar.mouseEnabled = tabBar.mouseChildren = true ; </li></ul></ul><ul><li>} </li></ul>
  13. 13. 另一种写法 <ul><li>public function setData( v :Array): void </li></ul><ul><li>{ </li></ul><ul><li>var list:Array = [ </li></ul><ul><li>new SetPropertyOper( this .tabBar,{mouseEnabled: false ,mouseChildren: false }), </li></ul><ul><li>// 禁用鼠标 </li></ul><ul><li>new TweenOper( this .render,500,{y:300,ease:Circ.easeIn}), </li></ul><ul><li>// 隐藏列表 </li></ul><ul><li>new SetPropertyOper( this .render,{data: v }), </li></ul><ul><li>// 设置数据 </li></ul><ul><li>new FunctionOper( this .scrollBar.resetContent,[true,false]), </li></ul><ul><li>// 让滚动区域回到顶端 </li></ul><ul><li>new TweenOper( this .render,500,{y:0,ease:Circ.easeOut}), </li></ul><ul><li>// 显示列表 </li></ul><ul><li>new SetPropertyOper( this .tabBar,{mouseEnabled: true ,mouseChildren: true }) </li></ul><ul><li>// 恢复鼠标 </li></ul><ul><li>]; </li></ul><ul><li>new Queue(list).execute(); // 队列执行 </li></ul><ul><li>} </li></ul>
  14. 14. Oper 类 <ul><li>上面的代码是先创建了一个数组,数组里面都是一些继承于 Oper 的类,每个对象表示着一个具体操作。这个对象创建出来并不会立即执行,而要使用对象的 execute 方法来启动。 </li></ul><ul><li>创建数组后,则创建了另一个特殊的 Oper : Queue ,它会代理并队列调用参数数组里的 Oper 对象的 execute 方法。 </li></ul><ul><li>这种做法比加监听意义更加明确。 </li></ul>
  15. 15. Queue <ul><li>这是一个特殊的 Oper ,参数是一个数组包含着其他的 Oper 对象。执行它将会顺序执行所有子对象。 </li></ul><ul><li>就像这样: new Queue(list).execute(); </li></ul>
  16. 16. SetPropertyOper <ul><li>SetPropertyOper( this .tabBar,{mouseEnabled: false ,mouseChildren: false }), </li></ul><ul><li>这个类用于设置某个对象的属性,第一个参数是对象实例,第二个参数是一个 JSON 对象,例如这段代码就是设置 mouseEnabled,mouseChildren 的值为 false </li></ul>
  17. 17. TweenOper <ul><li>TweenOper( this .render,500,{y:300,ease:Circ.easeIn}) </li></ul><ul><li>和 Tween 参数相似,只不过实例化这个对象并不会马上执行 Tween 操作,而需要手动执行 execute 方法。用于队列这点是必须的。 </li></ul>
  18. 18. FunctionOper <ul><li>FunctionOper( this .scrollBar.resetContent,[true,false]) </li></ul><ul><li>这个类非常简单,就是执行一个函数,第二个参数是参数数组。同样,你可以通过控制 execute 执行的时机来延迟执行这个函数。 </li></ul><ul><li>例如,你想加载一个文件然后完毕时执行一个方法,也可以这样写 </li></ul><ul><li>new Queue([new LoadOper(“a.txt”),new FunctionOper(rHandler)]).execute(); </li></ul><ul><li>这样在加载完 a.txt 之后便会继续执行 rHandler 方法 </li></ul>
  19. 19. …… <ul><li>除此之外还有很多 </li></ul><ul><li>但更重要的是,你可以自己创建一个 Oper 的派生类,便可以和其他类放置在同一个队列中执行 </li></ul>
  20. 20. 一个简单的例子(设置发光提示点击某个对象,点击后继续执行) <ul><li>public class ClickOper extends Oper </li></ul><ul><li>{ </li></ul><ul><ul><li>public var target:Sprite; </li></ul></ul><ul><ul><li>public function ClickOper(target:Sprite) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>this .target = target; </li></ul></ul></ul><ul><ul><ul><li>super (); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>public override function execute(): void </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>this .target.addEventListener(MouseEvent.CLICK,result); </li></ul></ul></ul><ul><ul><ul><li>this .target.filters = [ new GlowFilter(0xFFFFFF,1,16,16)] </li></ul></ul></ul><ul><ul><ul><li>super .execute(); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>public override function result(event:*= null ): void </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>this .target.removeEventListener(MouseEvent.CLICK,result); </li></ul></ul></ul><ul><ul><ul><li>this .target.filters = []; </li></ul></ul></ul><ul><ul><ul><li>super .result(event); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
  21. 21. GListBase 列表类
  22. 22. 刚才示例的代码,只是将 tabBar 的类型由 Gbutton 改成了 GListBase <ul><li>public class Panel extends GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public var titleText:GText; </li></ul><ul><li>public var mc:GMovieClip; </li></ul><ul><li>//public var tabBar:GButton; </li></ul><ul><li>public var tabBar: GListBase ; </li></ul><ul><li>public var scrollBar:GHScrollBar; </li></ul><ul><li>public var render: GListBase ; </li></ul><ul><li>public function Panel3() </li></ul><ul><li>{ </li></ul><ul><li>super ( &quot;asset.Panel&quot; ); </li></ul><ul><li>mc.setLabel( null ,1); // 让动画只播放一次 </li></ul><ul><li>render.type = UIConst.HORIZONTAL; </li></ul><ul><li>render.itemRender = Render; </li></ul><ul><li>scrollBar.setTarget(render,render.columnWidth * 2); </li></ul><ul><li>scrollBar.detra = render.columnWidth; </li></ul><ul><li>tabBar.type = UIConst.HORIZONTAL; </li></ul><ul><li>tabBar.itemRender = GButton; </li></ul><ul><li>tabBar.data = [ &quot;A-Z&quot; , &quot;0-10000&quot; ]; </li></ul><ul><li>tabBar.addEventListener(Event.CHANGE,tabChangeHandler); </li></ul><ul><li>tabBar.selectedIndex = 0; </li></ul><ul><li>} </li></ul><ul><li>private function tabChangeHandler(event:Event): void </li></ul><ul><li>{ </li></ul><ul><li>setData(getData(tabBar.selectedIndex)) </li></ul><ul><li>} </li></ul><ul><li>private function getData(type:int):Array </li></ul><ul><li>{ </li></ul><ul><li>var i:int; </li></ul><ul><li>var list:Array = []; </li></ul><ul><li>if (type == 0) </li></ul><ul><li>{ </li></ul><ul><li>for (i = 0;i < 26;i++) </li></ul><ul><li>{ </li></ul><ul><li>list[i] = String.fromCharCode(( &quot;A&quot; ).charCodeAt(0) + i); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>else </li></ul><ul><li>{ </li></ul><ul><li>for (i = 0;i < 100000;i++) </li></ul><ul><li>{ </li></ul><ul><li>list[i] = i.toString(); </li></ul><ul><li>} </li></ul>
  23. 23. <ul><li>GListBase 只负责复制子对象实现列表效果,它没有自己的大小概念,也没有滚动条。 </li></ul><ul><li>它可以像列表那样加上滚动条使用,也可以像上面那样直接作为 TabBar 存在。 </li></ul><ul><li>一共提供横向,纵向,横向平铺 3 种布局方式 </li></ul><ul><li>(不要忘了,能够复制的 MC 必须绑定类,否则无法复制,将永远直显示一个子对象) </li></ul>
  24. 24. 列表项的数量可以达到 1W <ul><li>GListBase 已经实现了对象池,只有显示出的子对象才会被实例化。因此显示 1W (或者更多)和显示 2 个消耗的资源是相同的。 </li></ul><ul><li>上面的例子中的第 2 个 Tab 页就使用了一个 1W 项数据的列表 </li></ul>
  25. 25. GMovieClip 动画扩展类
  26. 26. 其实之前的例子已经出现了一次 <ul><li>public var mc:GMovieClip; </li></ul><ul><li>public function Panel() </li></ul><ul><li>{ </li></ul><ul><li>super ( &quot; asset.Panel &quot; ); // 连接资源 </li></ul><ul><li>tabBar.data = &quot;A&quot; ; </li></ul><ul><li>nameText.text = &quot;@name&quot; ; </li></ul><ul><li>numText.text = &quot;A&quot; ; </li></ul><ul><li>mc.setLabel( null ,1); // 让动画只播放一次 </li></ul><ul><li>} </li></ul><ul><li>就像注释说的那样,这段代码的作用是设置 mc 的播放范围为 null (也就是全部帧),并指定播放 1 次。这是一个通用写法,也可以换成 mc.setLoop(1) 是一样的效果。当然,如果把 1 改成 2 ,那就是播放 2 次后停止。 </li></ul>
  27. 27. GMovieClip 关键属性 / 方法 <ul><li>frameRate 可以设置动画的播放帧频,当值为负时即为倒放,默认为舞台帧频 </li></ul><ul><li>frameRate 的播放控制是基于时间的,因此并不会因为 CPU 忙而产生拖慢,而只会跳帧,相对于拖慢更难被用户察觉。 </li></ul><ul><li>它是监听了 ENTER_FRAME 事件并以 getTimer 作为依据来决定当前帧的。并不会出现直接用 Timer 更新产生的闪烁,因此也不需要强制更新屏幕。 </li></ul>
  28. 28. GMovieClip 关键属性 / 方法 <ul><li>setLabel( 帧标签,播放次数 ) </li></ul><ul><li>帧标签就是 FLASH 时间线上对帧的命名,播放次数为 -1 时为无限循环(默认值) </li></ul><ul><li>queueLabel( 帧标签,播放次数 ) </li></ul><ul><li>这个方法需要和 setLabel 配合使用,它会在上一个动画播放完成后再执行。 </li></ul><ul><li>clearQueue() </li></ul><ul><li>清除当前的动画队列 </li></ul>
  29. 29. <ul><li>如果你的动画帧被命名分割为三个区域 : start , loop , end ,然后你希望先播放 start ,然后重复播放 loop 三次,最后播放完 end 然后停止,代码如下 </li></ul><ul><li>setLabel(“start”,1); </li></ul><ul><li>queueLabel(“loop”,3); </li></ul><ul><li>queueLabel(“end”,1); </li></ul><ul><li>整个播放过程当然也会对外发布 MovieEvent 事件,如果希望在动画完毕时处理一些事情,监听动画的 MOVIE_EMPTY 事件 </li></ul>
  30. 30. <ul><li>queueDestory() </li></ul><ul><li>新版本增加的方法,执行它后会在动画播放完毕后自动移除自己。于是不需要再去监听 MOVIE_EMPTY 事件了。毕竟这个需求就和动画仅播放一次一样常见…… </li></ul><ul><li>如果想反悔,可以再一次执行 clearQueue 方法。 </li></ul>
  31. 31. 并不只是矢量 <ul><li>GBitmapMovieClip 和它拥有几乎完全相同的属性和方法,但它所支持的是位图序列。 </li></ul><ul><li>与 MovieClip 不同,它的构造函数参数是一个由 BitmapData 组成的数组。而重要的帧标签部分,则是第二个可选参数:一个 FrameLabel 组成的数组。 </li></ul>
  32. 32. <ul><li>第二个参数并不是必须的。但如果想使用 queueLabel 这类方法的话,没有帧标签该如何操作?虽然,你也可以直接手动设置 currentFrame </li></ul><ul><li>你可以自己手动创建这个 FrameLabel 数组,也可以直接去取一个专门的空 MovieClip 的 currentLabels 属性(这是一条捷径) </li></ul>
  33. 33. 一个 GBitmapMovieClip 的实例 <ul><li>只贴出相关部分( BitmapSeparateUtil , FrameLabelUtil 也是库中的类 ) </li></ul><ul><li>var source:Array = BitmapSeparateUtil.separateBitmapData( new stand().bitmapData,56,91).concat(BitmapSeparateUtil.separateBitmapData( new walk().bitmapData,67,91)); </li></ul><ul><li>// 从 PNG 图片中切割成动画数组 </li></ul><ul><li>var labels:Array = FrameLabelUtil.createFromObject({ </li></ul><ul><li>&quot;down&quot; :1, &quot;left&quot; :9, &quot;right&quot; :17, &quot;up&quot; :25, </li></ul><ul><li>&quot;leftdown&quot; :33, &quot;rightdown&quot; :41, &quot;leftup&quot; :49, &quot;rightup&quot; :57, </li></ul><ul><li>&quot;walkdown&quot; :65, &quot;walkleft&quot; :73, &quot;walkright&quot; :81, &quot;walkup&quot; :89, </li></ul><ul><li>&quot;walkleftdown&quot; :97, &quot;walkrightdown&quot; :105, &quot;walkleftup&quot; :113, &quot;walkrightup&quot; :121 </li></ul><ul><li>}); </li></ul><ul><li>// 创建 FrameLabel 数组 </li></ul><ul><li>man = new GBitmapMovieClip(source,labels); // 创建动画对象 </li></ul><ul><li>man.frameRate = 10; </li></ul>
  34. 34. 动画缓存? <ul><li>矢量动画太复杂,播放不顺畅?这时候只能缓存。但具体应当如何去做呢? </li></ul><ul><li>当矢量和位图动画拥有同样的方法的时候,缓存动画就很简单了。下面的代码最后都能生成一个 GBitmapMovieClip 对象 bmc ,它是 mc 这个 MovieClip 对象的缓存,并可以直接 addChild 显示。 </li></ul><ul><li>方法 1 : </li></ul><ul><li>bmc = new GBitmapMovieClip(); </li></ul><ul><li>bmc.createFromMovieClip(mc); </li></ul><ul><li>方法 2 : </li></ul><ul><li>bmc = new GMovieClip(mc).toGBitmapMovieClip(); </li></ul>
  35. 35. SelectGroup& ViewStack 关于页面切换
  36. 36. asset.fla <ul><li>同理, tabBar 和 viewStack 元件类分别包含着 tab1,tab2,tab3 以及 render1,render2,render3 </li></ul><ul><li>整个元件链接了类名 asset.SelectGroup </li></ul>
  37. 37. Panel.as v4 ( 效果 ) <ul><li>public class Panel extends GBuilderBase </li></ul><ul><li>{ </li></ul><ul><li>public var tab1:ZoomButton; </li></ul><ul><li>public var tab2:ZoomButton; </li></ul><ul><li>public var tab3:ZoomButton; </li></ul><ul><li>public var tabBar:GBase; </li></ul><ul><li>public var render1:Panel; </li></ul><ul><li>public var render2:Panel2; </li></ul><ul><li>public var render3:Panel3; </li></ul><ul><li>public var viewStack:GViewState; </li></ul><ul><li>public var selectGroup:SelectGroup; </li></ul><ul><li>public function Panel() </li></ul><ul><li>{ </li></ul><ul><li>super ( &quot;asset.SelectGroup&quot; ); </li></ul><ul><li>// 按钮条 </li></ul><ul><li>selectGroup = new SelectGroup([ tab1,tab2,tab3 ], true ); </li></ul><ul><li>selectGroup.addEventListener(Event.CHANGE, changeHandler ); </li></ul><ul><li>selectGroup.selectedIndex = 0; </li></ul><ul><li>// 设置切换过渡 </li></ul><ul><li>viewStack.showFromRight = new TweenOper( null , 500, { x: -760, startAt:{x:0}, ease:Circ.easeInOut}, true ,1); </li></ul><ul><li>viewStack.showFromLeft = new TweenOper( null , 500, { x:760, startAt:{x:0}, ease:Circ.easeInOut}, true ,1); </li></ul><ul><li>viewStack.hideToRight = new TweenOper( null , 500, { x: -760 , ease:Circ.easeInOut}, false ,1); </li></ul><ul><li>viewStack.hideToLeft = new TweenOper( null , 500, { x:760 , ease:Circ.easeInOut}, false ,1); </li></ul><ul><li>} </li></ul><ul><li>private function changeHandler (event:Event): void </li></ul><ul><li>{ </li></ul><ul><li>viewStack.selectedIndex = selectGroup.selectedIndex; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>其中 ZoomButton 类见下页 </li></ul>
  38. 38. ZoomButton.as <ul><li>public class ZoomButton extends GButton </li></ul><ul><li>{ </li></ul><ul><li>public function ZoomButton(skin:*= null , replace:Boolean = true , separateTextField:Boolean = false , textPadding:Padding = null ) </li></ul><ul><li>{ </li></ul><ul><ul><li>super (skin, replace, separateTextField, textPadding); </li></ul></ul><ul><ul><li>this .delayCall = false ; // 取消延迟更新避免抖动 </li></ul></ul><ul><ul><li>this .upState.oper = new TweenOper( this ,100,{scaleX:1.0,scaleY:1.0}, false , 1); </li></ul></ul><ul><ul><li>this .overState.oper = new TweenOper( this ,100,{scaleX:1.4,scaleY:1.4}, false , 1); </li></ul></ul><ul><ul><li>this .downState.oper = new TweenOper( this ,100,{scaleX:1.0,scaleY:1.0}, false , 1); </li></ul></ul><ul><ul><li>this .selectedUpState.oper = this .selectedOverState.oper = this .selectedDownState.oper = new TweenOper( this ,100,{scaleX:1.4,scaleY:1.4}, false , 1); </li></ul></ul><ul><ul><li>this .disabledState.oper = this .selectedDisabledState.oper = new TweenOper( this ,100,{scaleX:1.0,scaleY:1.0}, false , 1); </li></ul></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>这个类直接继承于 GButton 并设置了一些效果的初始值,以实现缩放 </li></ul>
  39. 39. SelectGroup <ul><li>// 按钮条 </li></ul><ul><li>selectGroup = new SelectGroup([ tab1,tab2,tab3 ], true ); </li></ul><ul><li>selectGroup.addEventListener(Event.CHANGE, changeHandler ); </li></ul><ul><li>selectGroup.selectedIndex = 0; </li></ul><ul><li>这个类会将多个按钮传入,并提供 selectedIndex,selectedChild 属性以及 Change 事件来方便实现类似 ToggleButtonBar 的效果 </li></ul><ul><li>如果将第三个参数设置为” visible” ,还可以同样的指定多个对象仅有一个显示的效果 </li></ul>
  40. 40. GViewState <ul><li>此对象会将自己的 Children 当作多个 State 来处理,同时只显示其中的一个 </li></ul><ul><li>ViewState 主要的特性是提供了 showFromRight,showFromLeft,hideToRight,hideToLeft 这 4 个 Effect 属性,可以在切换的时候显示转场。 </li></ul>
  41. 41. Layout 布局
  42. 42. 当你并不需要动态布局的时候 <ul><li>可以在生成界面之后手动设置 UI 的各个属性,如果有些数组无法简单的少量代码写出来的话,可以使用 LayoutUtil 静态类。 </li></ul><ul><li>对齐 LayoutUtil.silder </li></ul><ul><li>从中部偏移 LayoutUtil.center </li></ul><ul><li>控制外框边距 LayoutUtil.metrics </li></ul><ul><li>百分比长宽 LayoutUtil.percent </li></ul><ul><li>横向排列 LayoutUtil.horizontal </li></ul><ul><li>纵向排列 LayoutUtil.vertical </li></ul>
  43. 43. 当你需要动态布局的时候 <ul><li>使用 Layout 系列对象,将容器作为参数传入,并设置必要的属性(方向,边距,间距等),当容器的子对象都是 GBase 对象时即可自动布局 </li></ul><ul><li>AbsoluteLayout 绝对布局,可设置子对象的 left,top,right,bottom 属性。 </li></ul><ul><li>LinearLayout 线性布局,子对象会按顺序排列在一起,可指定为 HORIZONTAL, VERTICAL, TILE 三种模式 </li></ul>
  44. 44. 编写自己的 Layout <ul><li>重写 Layout.as 的 layoutChildren 方法即可 </li></ul><ul><li>protected override function layoutChildren(x:Number, y:Number, w:Number, h:Number) { </li></ul><ul><li>var rx:Number = (w - paddingLeft - paddingRight) / 2; </li></ul><ul><li>var ry:Number = (h - paddingTop - paddingBottom) / 2; </li></ul><ul><li>var sx:Number = x + paddingLeft + rx; </li></ul><ul><li>var sy:Number = y + paddingTop + ry; </li></ul><ul><li>var len:int = target.numChildren; </li></ul><ul><li>var br:Number = this .rotation / 180 * Math.PI; </li></ul><ul><li>for ( var i:int = 0;i < len;i++){ </li></ul><ul><li>var obj:DisplayObject = target.getChildAt(i); </li></ul><ul><li>var r:Number = i / len * Math.PI * 2 + br; </li></ul><ul><li>var p:Point = new Point(sx + rx * Math.cos(r),sy + ry * Math.sin(r)); </li></ul><ul><li>obj.x = p.x; </li></ul><ul><li>obj.y = p.y; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>这段代码会让子对象以椭圆形式排列 </li></ul>
  45. 45. 当你希望容器本身也能根据子对象来决定自己大小的时候 <ul><li>Layout 对象需要实现 measureChildren 方法,最后通过执行 super .measureChildren(width,height) 来决定新的宽高 </li></ul><ul><li>LinearLayout 布局器默认已经开启了 measureChildren 。如果会造成困扰,可以设置 enabledMeasureChildren=false 来取消这个效果。 </li></ul>
  46. 46. GView <ul><li>GBox,GHBox,GVBox 已经默认包含了 LinearLayout 对象,因此只需要普通的 addChild 便能自动布局 </li></ul><ul><li>任何时候都可以重新执行 setLayout 来指定布局器 </li></ul>
  47. 47. 例:给刚才的例子加上布局功能 ( 效果 ) <ul><li>public var tab1:ZoomButton; </li></ul><ul><li>public var tab2:ZoomButton; </li></ul><ul><li>public var tab3:ZoomButton; </li></ul><ul><li>public var tabBar:GHBox;// 将 tabBar 的类型更改为 GHBox </li></ul><ul><li>public var render1:Panel; </li></ul><ul><li>public var render2:Panel2; </li></ul><ul><li>public var render3:Panel3; </li></ul><ul><li>public var viewStack:GViewState; </li></ul><ul><li>public var selectGroup:SelectGroup; </li></ul><ul><li>public function Panel(skin:*= null , replace:Boolean= true ) </li></ul><ul><li>{ </li></ul><ul><li>super ( &quot;asset.SelectGroup&quot; ); </li></ul><ul><li>tabBar.linearLayout.delayCall = false ; // 取消延迟布局可减少运动时的抖动现象 </li></ul><ul><li>tabBar.linearLayout.horizontalGap = 5; // 设置间距 </li></ul>

×