运行时动态修改 FMX 样式
简单说几个点:
1、FMX 框架下,样式是通过名称来标志的。
2、GetStyleObject 默认是克隆原始的样式,所以直接修改对象自身的 FResourceLink 实例,不会影响其它样式,如果要修改全部同一类型控件的样式,手动调用控件的 GetStyleObject(false) 来获取样式的原始实例即可,进行调整即可。
2、只修改当前实例的特定样式步骤:
通过 ResourceLink 保护属性获取对应的样式对象(受保护成员具体如何访问参考以前的文章)
直接修改对应的样式对象或者从 ResourceLink 中删除它,然后再创建一个新的 StyleName 同名的对象,添加到 ResourceLink 中
调用 ApplyStyle 保护方法,来应用样式
3、修改全局样式步骤:
通过 GetStyleObject 保护方法,获取原始的对象链接。
查找对应的样式对象实例
视需要直接修改对应的样式对象或者从 ResourceLink 中删除它,然后再创建一个新的 StyleName 同名的对象,添加到 ResourceLink 中
发送 TStyleChangedMessage 消息,这样所有的控件都会更新样式。如果只是当前控件,那么调用下NeedStyleLookup 即可。
参考代码:
uses syste m.Messaging; {$R *.fmx} type THackedListView=class(TListView) end; procedure TForm4.ComboColorBox1Change(Sender: TObject); var AStyle,AStyleLink:TFMXObject; begin // 仅修改 ListView1 的样式 // AStyleLink:=THackedListView(ListView1).ResourceLink; // 修改全局的 TListView 样式 AStyleLink:= THackedListView(ListView1).GetStyleObject(false); AStyle:=AStyleLink.FindStyleResource('selection'); if Assigned(AStyle) then begin if not (AStyle is TColorObject) then begin AStyleLink.RemoveObject(AStyle); AStyle:=TColorObject.Create(AStyleLink); AStyle.StyleName:='selection'; AStyleLink.AddObject(AStyle); end; (AStyle as TColorObject).Color:=ComboColorBox1.Color; //仅修改 ListView1 的样式 // THackedListView(ListView1).ApplyStyle; // 修改了全局样式,但当前只应用 ListView1 // ListView1.NeedStyleLookup; // 修改了全局样式,其它所有 ListView 都更新 TMessageManager.DefaultManager.SendMessage(Sender,TStyleChangedMessage.Create(StyleBook)); end; end;
上面的代码在 Windows 下是没有问题的,在其它平台,由于在克隆样式时,FMX 采用了不同的策略,所以需要做变动,参考代码如下:
type THackedListView = class(TListView) end; procedure ChangeListViewSelectionColor(AListView: TListView; ANewColor: TAlphaColor); overload; var AStyle, AStyleLink: TFmxObject; begin AStyleLink := THackedListView(AListView).ResourceLink; AStyle := AStyleLink.FindStyleResource('selection'); if Assigned(AStyle) then begin if not(AStyle is TColorObject) then begin AStyleLink.RemoveObject(AStyle); AStyle := TColorObject.Create(AStyleLink); AStyle.StyleName := 'selection'; AStyleLink.AddObject(AStyle); end; (AStyle as TColorObject).Color := ANewColor; THackedListView(AListView).ApplyStyle; end; end; procedure ChangeListViewSelectionColor(ANewColor: TAlphaColor); overload; var I: Integer; procedure ApplyColor(AParent: TFmxObject); var AIndex: Integer; begin if AParent is TListView then ChangeListViewSelectionColor(TListView(AParent),ANewColor); for AIndex := 0 to AParent.ChildrenCount - 1 do ApplyColor(AParent.Children[AIndex]); end; begin for I := 0 to Screen.FormCount - 1 do ApplyColor(Screen.Forms[I]); end;