运行时动态修改 FMX 样式

admin3个月前教程189

简单说几个点:

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;

录屏_选择区域_20220917113911.gif

上面的代码在 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;


标签: delphifmx

相关文章

高效处理在主线程中显示后台线程处理进度

先看经典的处理方法:TThread.CreateAnonymousThread(     procedure     ...

Delphi 泛型中数据内容比较

第一:你需要引入 System.Generics.Defaults 单元,系统默认实现的比较方法,都在该单元定义。第二:你要明确下你的需求,是只比较相等就可以,还是要比较大小。IEqualityCom...

Delphi 函数的内部函数在匿名回调函数中无法使用的一种解决办法

这个问题很简单,将对应的函数改写赋值到一个匿名函数变量即可。function test;   function add(x,y:Integer):Intege...

一个共享的计时器类封装

QDAC 4.0 中已经包含了此单元,名称改为qdac.timer.share,使用 TQShareTimer 来做相关处理。这个是一个精度为秒的共享定时器实现,可以秒为单位创建多个共享的定时器,这些...