以下是 focusColor 無效的設定範例:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal" verticalAlign="middle">
<mx:Style>
global {
focusColor: #FFFFFF;
}
Button {
focusColor: #FFFFFF;
}
</mx:Style>
<mx:Button id="btn1" label="Button 01" />
<mx:Button id="btn2" label="Button 02" />
</mx:Application>
實際測試就會發現,無論是在 Flex 2 or 3b3
focusColor 都沒有效果
還是得要下去看 Flex Source Code 除錯
Flex 內的 Focus Skin 預設是使用 HaloFocusRect Class
而其中 updateDisplayList 方法是主要負責繪圖的
由原始碼可以看出,HaloFocusRect 是先取用 focusColor
假如 focusColor 不存在,才會使用 themeColor
這裡是很正常的行為
override protected function updateDisplayList(w:Number, h:Number):void
{
super.updateDisplayList(w, h);
var focusBlendMode:String = getStyle("focusBlendMode");
var focusAlpha:Number = getStyle("focusAlpha");
var focusColor:Number = getStyle("focusColor");
var cornerRadius:Number = getStyle("cornerRadius");
var focusThickness:Number = getStyle("focusThickness");
var focusRoundedCorners:String = getStyle("focusRoundedCorners");
var themeColor:Number = getStyle("themeColor");
var rectColor:Number = focusColor;
if (isNaN(rectColor))
rectColor = themeColor;
var g:Graphics = graphics;
g.clear();
blendMode = focusBlendMode;
......
於是再往下追蹤,發現 UIComponent 會重設 focusSkin 的 focusColor
/**
* Adjust the focus rectangle.
*
* @param The component whose focus rectangle to modify.
* If omitted, the default value is this UIComponent object.
*/
protected function adjustFocusRect(obj:DisplayObject = null):void
{
if (!obj)
obj = this;
// Something inside the lisder has a width and height of NaN
if (isNaN(obj.width) || isNaN(obj.height))
return;
var fm:IFocusManager = focusManager;
if (!fm)
return; // we've been unparented so ignore
var focusObj:IFlexDisplayObject = IFlexDisplayObject(getFocusObject());
if (focusObj)
{
var rectCol:Number;
if (errorString && errorString != "")
rectCol = getStyle("errorColor");
else
rectCol = getStyle("themeColor");
var thickness:Number = getStyle("focusThickness");
if (focusObj is IStyleClient)
{
IStyleClient(focusObj).setStyle("focusColor", rectCol);
}
......
從原始碼看來,絲毫沒有檢查 focusColor 就直接用 themeColor 硬幹下去了
真是無言......
解決方式,自行繼承組件,覆寫 adjustFocusRect 方法:
package {
import flash.display.*;
import mx.controls.Button;
import mx.core.*;
import mx.styles.*;
public class MyButton extends Button {
public function MyButton() {
super();
}
override protected function adjustFocusRect(obj:DisplayObject = null):void{
super.adjustFocusRect(obj);
var focusObj:IFlexDisplayObject = IFlexDisplayObject(mx_internal::getFocusObject());
if (focusObj is IStyleClient) {
var focusColor:Number = this.getStyle("focusColor");
if (!isNaN(focusColor)) {
IStyleClient(focusObj).setStyle("focusColor", focusColor);
}
}
}
}
}
可是假如用到大量組件,這樣一個一個覆寫也不是辦法
所以另一個方式就是覆寫 HaloFocusRect,硬在 updateDisplayList 之前把顏色覆蓋下去
MyHaloFocusRect.as
package {
import mx.skins.halo.HaloFocusRect;
public class MyHaloFocusRect extends HaloFocusRect {
public function MyHaloFocusRect() {
super();
}
override protected function updateDisplayList(w:Number, h:Number):void{
this.setStyle("focusColor", 0xFFFFFF);
super.updateDisplayList(w, h);
}
}
}
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:comp="*"
layout="horizontal" verticalAlign="middle">
<mx:Style>
global {
focusSkin: ClassReference("MyHaloFocusRect");
}
</mx:Style>
<mx:Button id="btn1" label="Button 01" />
<mx:Button id="btn2" label="Button 02" />
</mx:Application>