[FMX]教程:运行时动态修改 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;
分享到: