2008年6月27日 星期五

Flex 技巧 - 将资料绑定封装起来   [+/-]

Ticore's Blog

之前介绍了 纯手工设置 Flex DataBinding 的方式
不过那挺麻烦的
假如想要将 DataBinding 封装起来,保留部分弹性
又不想要那么麻烦的设置方式
不妨可以试试看以下的方式

在这个例子中,完全的将 DataBinding 封装在一个 MXML Component 中
必须要指定好目标物,Component 内的 DataBinding 才会发生作用
想要停止 DataBinding 也很简单,只要将目标属性设为 null 就好

甚至可以对一份资料,准备多个 DataBinding Component
只要在运行期动态替换 Component,就能达到切换 DataBinding 行为的目的
其实还挺方便的

Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  verticalAlign="middle" backgroundColor="#FFFFFF"
  creationComplete="init();" fontSize="12">
 <mx:Script>
  <![CDATA[
   public var comp:BindingComp;
   
   public function init():void{
    comp = new BindingComp();
    comp.initialize();
   }
  ]]>
 </mx:Script>
 <mx:HBox>
  <mx:Label text="No 1:" />
  <mx:NumericStepper id="no1" maximum="100" />
 </mx:HBox>
 <mx:HBox>
  <mx:Label text="No 2:" />
  <mx:NumericStepper id="no2" maximum="100" />
 </mx:HBox>
 <mx:CheckBox id="chk" label="DataBinding Enabled"
   change="comp.target = chk.selected ? this : null;" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

BindingComp.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:UIComponent xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Script>
  <![CDATA[
   [Bindable]
   public var target:Main;
   
   public function doBinding1(... args:*):void{
    if (target) target.no2.value = target.no1.value;
   }
   public function doBinding2(... args:*):void{
    if (target) target.no1.value = target.no2.value;
   }
  ]]>
 </mx:Script>
 <mx:Model>
  {doBinding1(target.no1.value)}
 </mx:Model>
 <mx:Model>
  {doBinding2(target.no2.value)}
 </mx:Model>
</mx:UIComponent>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

线上测试示范:

相关连结:
Flex - 纯手工设置 DataBinding 的方式
Flex 技巧 - BindingManager 使用方式
Flex 技巧 - 观察 Data Binding 资料变化
Flex Tip - 在 Data Binding 内使用 [...] 运算子
Flex 2 Bindable Metadata Tag 背后实际作用
Flex 2.0 - 以 ActionScript 3.0 动态设置 Data Binding

Read more...

2008年6月25日 星期三

关于 MMUG.TW 论坛暂停服务   [+/-]

Ticore's Blog

台湾 macromedia 使用者俱乐部论坛 因为一些说来话长的原因,暂停服务一阵子!

若是您在这段期间有什么 Flash 的问题 "急着" 想要找人请教与讨论的话
欢迎到 Google Group 平台的 AUG.TW 继续发问:
http://groups.google.com/group/augtw

Read more...

2008年6月18日 星期三

Flex SDK 马歇尔计画   [+/-]

Ticore's Blog

Marshall Plan 原文有点长,主要只有两件事情:

  • 不同版本交互支持 (Cross-Versioning):
    不同版本 Flex 编译的 SWFs 可以被放在相同的 SecurityDomain 运行
    但是却可以有不同的 ApplicationDomain

  • 不信任的应用程序支持 (Untrusted Application):
    被装入到不同 SecurityDomain 的 SWFs 将不能访问主应用程序或是 Stage 与其它受限的资源

这个计画将可能会在 Flex 3.1 开始支持
未来不同版本的 Flex 应用程序可以做混搭了
个人猜测,这计画背后更重要的意义是 Flash 与 Flex 应用程序混搭

不过在那之前,Adobe 可能要先把 ApplicationDomain 的 Bug 处理掉吧~

Read more...

2008年6月17日 星期二

Adobe AIR 1.1 出了   [+/-]

Ticore's Blog

Adobe AIR 1.1 出了,HTML Input Text 终于支持双位元文字输入法了

Download Adobe AIR SDK
Adobe AIR extension for Dreamweaver CS3
Installing Adobe Air 1.1 Update for Flash CS3 Professional

Read more...

2008年6月14日 星期六

AS 技巧 - Layer BlendMode 的用处   [+/-]

Ticore's Blog

Flash Player 8 新增的混合模式功能中的图层模式 (Layer)
一般使用起来或许觉得没有什么特别的用处
说明文档上写得更是令人雾茫茫
简单的说,只是让 DisplayObject 子对象预先混和颜色而已

基本上,除了 Normal 之外的混合模式,都会强迫预先混和子对象颜色
但是其它混合模式都是有特殊效果的
假如不需要那些效果,但是又要强迫预先混合颜色时
就要用 Layer 混合模式了

对于像是 Flex 这样由大量的 DisplayObject 组合而成的组件
遇到需要淡入、淡出效果时
即使是在最外层设置 Alpha 透明度
每个子对象仍会先被单独套用 Alpha 效果再叠合成一张图
这样就会有某些位置颜色特别突兀不透明

此时 Layer 混合模式就非常好用了
它可以让整个表单先叠合成一张图再进行 Alpha 效果
可以确保组件颜色看起来不会特别突兀

以下是用 Flex 作的简单测试
可以容易观察到多层嵌套组件在不同 Alpha, BlendMode 的效果

<?xml version="1.0"?>
<mx:Application layout="vertical" fontSize="12" backgroundColor="#FFFFFF"
   xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Style>
  HBox.whiteBox {
   paddingTop: 15px;
   paddingBottom: 15px;
   paddingLeft: 15px;
   paddingRight: 15px;
   backgroundColor: #000000;
  }
 </mx:Style>
 <mx:HBox styleName="whiteBox" alpha="{alphaSlider.value}"
    blendMode="{blendModeCb.value ? blendModeCb.value : 'normal'}">
  <mx:HBox styleName="whiteBox">
   <mx:HBox styleName="whiteBox">
    <mx:HBox styleName="whiteBox" />
   </mx:HBox>
  </mx:HBox>
 </mx:HBox>
 
 <mx:HRule width="100%" />
 <mx:HBox verticalAlign="middle">
  <mx:Label text="BlendMode: " />
  <mx:ComboBox id="blendModeCb">
   <mx:dataProvider>
    ["normal", "layer", "darken", "invert", "hardlight"]
   </mx:dataProvider>
  </mx:ComboBox>
 </mx:HBox>
 <mx:HBox verticalAlign="middle">
  <mx:Label text="Alpha: " />
  <mx:HSlider id="alphaSlider" value="0.5"
    tickValues="[0, 0.5, 1]" labels="[0, 0.5, 1]"
    minimum="0" maximum="1" liveDragging="true" />
 </mx:HBox>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

线上测示示范:

相关连结:
Flex Label, TextField 半透明小技巧
Flash 8 半透明输入、动态文字字段

Read more...

2008年6月10日 星期二

Flex - 纯手工设置 DataBinding 的方式   [+/-]

Ticore's Blog

Flex 的 DataBinding Expression 功能虽然非常方便
不用自行调用 addEventListener,省去了不少程序码
但是换个角度看,Flex DataBinding 其实是有点缺乏弹性
不用自行添加监听事件,同时也意味着不能移除监听事件

然而,自行利用 addEventListener 方式实作的 DataBinding
感受好像又没有 Flex Compiler 生成的好~
于是想要观察 Flex Compiler 生成的程序码
进而自行模仿实作 DataBinding

想要观察 Flex Compiler 生成的 ActionScript 很简单
只要添加编译参数 -keep-generated-actionscript=true
就可以在 /src/generated 下查找了

举例来说,想要仿真以下的 DataBinding Expression:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   backgroundColor="#FFFFFF" layout="vertical" fontSize="12">
   
  <mx:Label text="Binding Source:" />
  <mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" />

  <mx:Label text="Binding Destination:" />
  <mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{slider1.value}" />
  
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

步骤有点多~~

  1. 实作 mx.binding.IBindingClient; 界面

  2. 汇入必要的 Class:

    import mx.binding.*;
    import mx.binding.utils.*;
    import mx.core.mx_internal;
    

  3. 宣告 Bindings, Watchers 等属性:

    mx_internal var _bindings : Array = [];
    mx_internal var _watchers : Array = [];
    mx_internal var _bindingsByDestination : Object = {};
    mx_internal var _bindingsBeginWithWord : Object = {};
    

  4. 创建 Bindings 与 Watchers:

    mx_internal::_bindings[0] = new Binding(this,
     function():* {return slider1.value;},
     function(sourceReturnValue:*):void {slider2.value = sourceReturnValue;},
     "slider2.value");
    
    mx_internal::_watchers[0] = new PropertyWatcher("slider1",
       {propertyChange: true},
       [mx_internal::_bindings[0]],
       function(propertyName:String):* { return this[propertyName]; });
    
    mx_internal::_watchers[1] = new PropertyWatcher("value",
       {valueCommit: true, change: true},
       [mx_internal::_bindings[0]], null);
    
    mx_internal::_watchers[0].updateParent(this);
    mx_internal::_watchers[0].addChild(mx_internal::_watchers[1]);
    
    mx_internal::_bindings[0].execute();
    

最后一个步骤看起来就有点复杂了
Binding 的功能有点类似 Event Handler,负责运行 DataBinding 运算
而 Watcher 则是类似 Event Listener,负责监听资料来源的变化
为什么不用标准的 Event Listener 机制
看 Flex Source 上写的是因为效能考量

先看一下 mx.binding.Binding 类别的使用方式
public function Binding(document:Object, srcFunc:Function, destFunc:Function, destString:String)

  • document: binding 目标的文档
  • srcFunc: 用来取值的函式
  • destFunc: 将值指定到目的地的函式
  • destString: 用来告诉 ValidationManager 验证该字段

至于 Watcher 其实只是一个上层类别
实际使用时,需要视 Binding Source 种类决定使用哪一种子 Watcher
XMLWatcher, PropertyWatcher, StaticPropertyWatcher, RepeaterItemWatcher, RepeaterComponentWatcher, FunctionReturnWatcher, ArrayElementWatcher

Watcher 有一个最特别的地方是,它具有父子关系
上层的父 Watcher 会触发下层的子 Watcher 对象
可以藉由以下 Watcher 函式设置:

public function updateParent(parent:Object):void;
public function addChild(child:Watcher):void;
public function removeChildren(startingIndex:int):void;
public function updateChildren():void;

综合上述的步骤
完整手工设置的 DataBinding MXML 程序码如下:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   backgroundColor="#FFFFFF" layout="vertical" fontSize="12"
   implements="mx.binding.IBindingClient"
   creationComplete="onCreateComplete();">
  
  <mx:Script>
   <![CDATA[
    import mx.binding.*;
    import mx.binding.utils.*;
    import mx.core.mx_internal;
    
    mx_internal var _bindings : Array = [];
    mx_internal var _watchers : Array = [];
    mx_internal var _bindingsByDestination : Object = {};
    mx_internal var _bindingsBeginWithWord : Object = {};
    
    public function onCreateComplete():void{
     
     mx_internal::_bindings[0] = new Binding(this,
      function():* {return slider1.value;},
      function(sourceReturnValue:*):void {slider2.value = sourceReturnValue;},
      "slider2.value");
     
     // mx_internal::_bindings[0].mx_internal::isEnabled = false;
     
     mx_internal::_watchers[0] = new PropertyWatcher("slider1",
        {propertyChange: true},
        [mx_internal::_bindings[0]],
        function(propertyName:String):* { return this[propertyName]; });
     
     mx_internal::_watchers[1] = new PropertyWatcher("value",
        {valueCommit: true, change: true},
        [mx_internal::_bindings[0]], null);
     
     mx_internal::_watchers[0].updateParent(this);
     mx_internal::_watchers[0].addChild(mx_internal::_watchers[1]);
     
     mx_internal::_bindings[0].execute();
     
     // BindingManager.debugBinding("slider2.value");
    }
   ]]>
  </mx:Script>
  
  <mx:Label text="Binding Source:" />
  <mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" />

  <mx:Label text="Binding Destination:" />
  <mx:HSlider id="slider2" snapInterval="1" maximum="100" />
  
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

相关连结:
Flex 技巧 - 将资料绑定封装起来
Flex 技巧 - BindingManager 使用方式
Flex 技巧 - 观察 Data Binding 资料变化
Flex Tip - 在 Data Binding 内使用 [...] 运算子
Flex 2 Bindable Metadata Tag 背后实际作用
Flex 2.0 - 以 ActionScript 3.0 动态设置 Data Binding
Soph-Ware Associates Blog - Data Binding in Flex, Part I
Soph-Ware Associates Blog - Data Binding in Flex, Part II

Read more...

2008年6月8日 星期日

Flex 技巧 - BindingManager 使用方式   [+/-]

Ticore's Blog

Flex 的 mx.binding.*; 内有许多未公开的类别
主要都是给 MXML Compiler 使用的
其中 mx.binding.BindingManager 便是负责管理所有的 DataBinding 运作
BindingManager 内有一些静态函式还蛮有用的
列举如下:

  • BindingManager.setEnabled(document:Object, isEnabled:Boolean):void;
    用来 停止/启动 Flex Application/Component 内 Data Binding

  • BindingManager.executeBindings(document:Object, destStr:String, destObj:Object):void;
    运行被指定 Data Binding Expression

  • BindingManager.debugBinding(destinationString:String):void;
    对指定的 Data Binding Expression 进行除错

以下是简单的 BindingManager 使用示范程序:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   backgroundColor="#FFFFFF" layout="vertical" fontSize="12"
   creationComplete="onCreateComplete();">
  <mx:Script>
   <![CDATA[
    import mx.binding.*;
    public function onCreateComplete():void{
     BindingManager.debugBinding("slider2.value");
    }
   ]]>
  </mx:Script>
  
  <mx:Label text="Binding Source:" />
  <mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" />

  <mx:Label text="Binding Destination:" />
  <mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{slider1.value}" />
  
  <mx:CheckBox id="chk" label="Binding Enabled" selected="true"
    change="BindingManager.setEnabled(this, chk.selected); btn.enabled = chk.selected;" />
    
  <mx:Button id="btn" label="Execute DataBinding"
    click="BindingManager.executeBindings(this, 'slider2.value', null);" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

测试输出结果:

Binding: destString = slider2.value, srcFunc result = 54
Binding: destString = slider2.value, srcFunc result = 59
Binding: destString = slider2.value, srcFunc result = 81
Binding: destString = slider2.value, srcFunc result = 41

相关连结:
Flex 技巧 - 将资料绑定封装起来
Flex - 纯手工设置 DataBinding 的方式
Flex 技巧 - 观察 Data Binding 资料变化
Flex Tip - 在 Data Binding 内使用 [...] 运算子
Flex 2 Bindable Metadata Tag 背后实际作用
Flex 2.0 - 以 ActionScript 3.0 动态设置 Data Binding

Read more...

2008年6月6日 星期五

Flex 技巧 - 观察 Data Binding 资料变化   [+/-]

Ticore's Blog

Flex Data Binding 功能让开发者不用写太多的程序码
就能做到资料系结功能
但是要除错的时候就比较不太方便
Data Binding Expression 区块内很多语法都不能使用
当 Data Binding 被触发时,想要观察资料变化就不太方便

以下分享一个小技巧,可以很简单的观察 Data Binding 前后资料的变化

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   backgroundColor="#FFFFFF" layout="vertical" fontSize="12">
  
  <mx:Label text="Binding Source:" />
  <mx:HSlider id="slider1" snapInterval="1" maximum="100" />

  <mx:Label text="Binding Destination:" />
  <mx:HSlider id="slider2" snapInterval="1" maximum="100"
    value="{trace('Before :', slider2.value),
    setTimeout(function():void{trace('After :', slider2.value);}, 0), slider1.value}"/>
  
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

由于 Data Binding Expression 内不能使用 ";" 结尾的陈述式
所以使用 "," 作区隔,只有最后一个 Expression 会被当作值指定给目标
这样在前面就可以 trace 到变化之前的值
配合 setTimeout 又可以观察到变化之后的值

相关连结:
Flex 技巧 - 将资料绑定封装起来
Flex - 纯手工设置 DataBinding 的方式
Flex 技巧 - BindingManager 使用方式
Flex Tip - 在 Data Binding 内使用 [...] 运算子
Flex 2 Bindable Metadata Tag 背后实际作用
Flex 2.0 - 以 ActionScript 3.0 动态设置 Data Binding

Read more...

2008年6月3日 星期二

Flash 内嵌动态文字与样式的问题   [+/-]

Ticore's Blog

问题出处:动态文字字段的问题

问题描述:

于 Flash 舞台上
放置两个动态文字字段,选择相同的字体
第一个不嵌入任何字集,样式设为 regular
第二个嵌入数字字符集,样式设为 bold
于运行期动态重设第二个文字字段内容
该文字字段将无法表现新的文字内容

简化过后的问题 Demo 程序如下:

注意,测试的时候不要先选定 txt2 内的文字
只要一选定过,就不过出现问题了

原始文件下载

这个问题其实还挺复杂的,由许多的特性共同影响,分述如下~

Flash TextField 与 Embed Font 特性:

特性 1.
基本上,Flash 的内嵌字体,即使是相同的字体名称
不同的样式 (regular, bold, italic) 会被当作完全不同的字体处理

特性 2.
Flash 内所有时间轴预置 TextField 内嵌字体都是可以共用的

依据特性 1. 2.,可以做一个简单的测试
于 Flash 舞台上放置两个动态文字字段
第一个文字字段仅嵌入 Airal regular 数字字集
第二个文字字段仅嵌入 Airal bold 英文字母字集
动态将第二个文字字段样式设为 regular 之后
那么该文字字段只能表现数字了~~

特性 3.
一个 SWF 内仅嵌入单一字体样式 (eg. Arial regular) 时
动态使用同一字体但是不同样式 (eg. Arial bold) 的文字字段
将会使用该字体唯一嵌入样式 (eg. Arial regular) 作为替代字体

特性 4.
将 TextField.text 内容重设时
TextField 内的文字样式 bold, italic 也会被重设为默认的样式
AS3 TextField.appendText 则不会重设样式

ActionScript 3.0 测试程序:

package {
 import flash.display.*;
 import flash.text.*;

 public class Main1 extends MovieClip {

  public function Main1() {

   var txt:TextField = new TextField();
   var tf:TextFormat = new TextFormat();
   tf.bold = true;
   tf.italic = true;


   // TextField 内不含文字内容时,无法套用 bold, italic 样式
   txt.text = "";
   txt.setTextFormat(tf);
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : null , tf.italic : null

   txt.text = "123";
   txt.setTextFormat(tf);
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : true , tf.italic : true


   // 改变 TextField.text 内容时,bold, italic 样式被重设
   txt.text="123";
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : false , tf.italic : false

   tf.bold = true;
   tf.italic = true;
   txt.setTextFormat(tf);
   txt.text += "123";
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : false , tf.italic : false


   // 使用 appendText 改变 TextField.text 内容时,bold, italic 样式会被保留
   tf.bold = true;
   tf.italic = true;
   txt.setTextFormat(tf);
   txt.appendText("456");
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : true , tf.italic : true
   
   
   // 指定 TextField.text 内容前,调用 setSelection,bold, italic 样式会被保留
   tf.bold = true;
   tf.italic = true;
   txt.setTextFormat(tf);
   txt.setSelection(0, 1);
   txt.text = "456";
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : true , tf.italic : true
   
   
   // 改变 TextField.text 内容时,bold, italic 会被重设为 defaultTextFormat
   tf.bold = true;
   tf.italic = false;
   txt.setTextFormat(tf);
   tf.bold = false;
   tf.italic = true;
   txt.defaultTextFormat = tf;
   txt.text = "456";
   tf = txt.getTextFormat();
   trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
   // tf.bold : false , tf.italic : true
   
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

了解上述特性之后,答案就很明显了~~

解决方式:
1. 对于同一字体不同的样式,均嵌入相同的字集
2. 当 TextField.text 内容重设时,自行回设正确的 Bold, Italic 样式
3. 利用 TextField.defaultTextFormat 设置 Bold, Italic 设置样式
4. 于 TextField.text 内容重设之前,调用 TextField.setSelection(0, 1);

相关连结:
Flash 技巧 - 预先编译嵌入字体

Read more...