简介:TMS FMX UI Pack 3.7.3.0 是面向 Delphi FireMonkey 开发者的界面控件套件,适用于 XE7 至 10.4 Sydney 各版本,帮助开发者快速构建跨平台桌面与移动端 UI,省去从零绘制控件的成本。资源以源码加示例形式提供,包内共 1410 个文件,涵盖 386 个 pas 源码、344 个 dcu 编译单元、111 个 res 资源、87 个 inc 包含文件、69 个 dproj 工程及 59 个 fmx 窗体文件,另有样式、图标、文档与多语言 aff 文件,压缩包约 58.28MB。安装时在 IDE 中打开 TMSFMXPackPkgD*.dproj 与 TMSFMXPackPkgDED*.dproj 并右键 install 即可完成组件注册。已有 578 人学习下载,适合需要研究 FMX 控件实现、复用现成界面组件或进行多语言适配的 Delphi 中高级开发者参考。
1. TMS FMX UI Pack 3.7.3.0 在 D10.4 上的真实定位:它到底解决什么问题
如果你正在用 Delphi 10.4 Sydney 做 FireMonkey 跨平台界面,大概率遇到过这种局面:原生 FMX 控件能跑,但样式单薄、动画生硬、列表滚动一多就掉帧,产品经理拿着移动端设计稿问你“这个卡片阴影和圆角渐变能不能做”,你只能手动拼 StyleBook,拼到怀疑人生。TMS FMX UI Pack 就是冲着这个场景来的——它是一套面向 FireMonkey 的第三方控件与样式集合,覆盖网格、图表、列表、导航、输入、对话框等常见 UI 构件,版本号 3.7.3.0 对应的是能挂在 D10.4 上的一个稳定分支。它不改变 FMX 的渲染底层,而是在其之上补了一层“开箱即用”的控件库和主题体系。适合谁?适合已经决定用 Delphi 做跨平台桌面/移动端、不想从零造轮子、又需要界面达到商业产品水准的团队。不适合谁?如果你的项目只用 VCL、或者对包体积极度敏感、或者坚持零第三方依赖,那这套东西对你价值有限。下面按“先跑通、再调优、后避坑”的顺序拆开讲。
2. 把 TMS FMX UI Pack 3.7.3.0 装进 D10.4:从包管理到第一个可运行界面
2.1 安装前的环境核对与包文件识别
D10.4 的 IDE 对包(Package)的编译目标平台有明确要求,装之前先确认三件事:一是 IDE 版本确实是 10.4(Help → About 里看版本号),二是已安装的 FMX 运行时库完整(默认安装即有),三是拿到的是对应 D10.4 的包源或已编译包。TMS 这类库通常提供源码包,目录里会按 Delphi 版本分文件夹,D10.4 对应的通常是带 “104” 或 “Sydney” 标识的子目录。不要混用其他版本的 dcpu 或 bpl,否则会出现“包已加载但控件面板不出现”的玄学问题。
安装的常见做法是:先编译运行时包(Runtime Package),再编译设计期包(Design Package),最后在 IDE 里 Install 设计期包。运行时包负责把控件代码链进你的 exe,设计期包负责把控件注册到 Tool Palette。顺序反了,IDE 会报找不到运行时依赖。
# 以命令行方式编译运行时包(示例路径,按实际目录替换) # 进入 D10.4 对应的包目录 cd "TMSFMXUIPack\Packages\D104" # 用 dcc32 编译 Win32 运行时包,-Q 静默,-B 全量重建 dcc32 -Q -B TMSFMXUIpack_R.dpk # 再编译设计期包,设计期包会引用运行时包 dcc32 -Q -B TMSFMXUIpack_D.dpk逻辑说明:-B强制重新编译所有单元,避免旧 dcpu 残留导致的“改了代码没生效”;-Q减少输出干扰。参数上,如果你要出 Android/iOS 目标,需要在 IDE 里对移动平台单独编译,命令行方式对移动目标支持有限,建议移动端直接在 IDE 的 Project Manager 里右键包 → Compile 对应平台。
编译通过后,在 IDE 中打开设计期包对应的 dpk,右键 Install。安装成功后,Tool Palette 里会出现 TMS 分类。此时新建一个 FMX 多设备应用,拖一个 TMS 的网格或列表控件到窗体上,能正常显示即说明链路通了。
2.2 最小可运行示例:用 TMS 控件替换原生列表
光装上不算跑通,得验证它在真实数据绑定和滚动场景下是否正常。下面给一个最小示例:用 TMS 的列表类控件展示一批数据,并套一个内置主题。
procedure TForm1.FormCreate(Sender: TObject); var i: Integer; Item: TTMSFMXListGroupItem; begin // 清空设计期可能残留的项 TMSFMXList1.Items.Clear; // 关闭自动排序,避免插入顺序被打乱 TMSFMXList1.Sorted := False; for i := 1 to 50 do begin // 每个分组项承载一行数据 Item := TMSFMXList1.Items.Add as TTMSFMXListGroupItem; Item.Text := '设备节点 ' + IntToStr(i); Item.Detail := '状态:在线 延迟:' + IntToStr(20 + i mod 30) + ' ms'; end; // 应用内置主题,主题名以实际安装版本提供的为准 TMSFMXList1.StyleLookup := 'tmsliststyle'; end;逻辑说明:Items.Add返回的是基类项,需要as转型到分组项才能用Detail这类扩展属性;Sorted := False是因为默认排序在动态插入时会引起重排闪烁,先关掉更稳。参数上,StyleLookup的值不是随便写的字符串,它对应库内注册的样式名,写错不会报错但样式不生效,这是新手最容易翻车的地方——界面看起来“没变化”,其实是你样式名对不上。
跑起来后重点看两件事:滚动 50 行以上是否掉帧、窗口缩放时布局是否错位。如果掉帧,先别怀疑库,检查是否在OnPaint里做了重活;如果错位,检查控件的Align和Margins是否和父容器冲突。
2.3 主题与样式体系的接入方式
TMS FMX UI Pack 的样式不是靠你手写 StyleBook 一条条描边,而是提供了一套预置主题,通过StyleBook或控件级StyleLookup挂载。常见做法是:在窗体上放一个StyleBook,加载库自带的样式文件(通常是 .style 或编译进资源的样式),然后让控件通过StyleLookup引用其中的键。
这里有个选型理由要讲清楚:为什么不直接改原生 FMX 样式?因为原生 StyleBook 的继承链在跨平台时表现不一致,Windows 上好看的样式到 Android 上可能因为字体度量差异而错位。TMS 的主题体系对多平台做了适配,代价是你得接受它的视觉规范,深度定制仍要回到 StyleBook 层面改。
接入步骤:窗体放StyleBook→ 加载主题资源 → 给需要统一风格的控件设StyleLookup。如果只想局部改,可以只对某个控件设StyleLookup,不动全局。注意:全局 StyleBook 和控件级 StyleLookup 同时存在时,控件级优先,但全局主题里的字体设置仍会影响未显式覆盖的控件。
3. 参数调优与性能边界:TMS FMX UI Pack 在 D10.4 上怎么设才不卡
3.1 列表与网格的虚拟化开关
TMS 的列表和网格类控件大多支持虚拟化(只渲染可视区域内的项)。这个开关直接决定大数据量下的帧率。默认值在不同控件上不一样,有的默认开,有的默认关,不能想当然。
以列表为例,关键属性通常是Virtualized或类似的布尔项。开启后,控件只为当前视口内的项创建可视对象,滚动时复用。代价是:如果你在项上挂了自定义的、依赖“项一直存在”的逻辑(比如后台定时刷新某一项的文本),虚拟化后项被回收,逻辑就会失效。
// 开启虚拟化,适合 200 项以上的场景 TMSFMXList1.Virtualized := True; // 设置项高度,虚拟化依赖固定高度来计算视口范围 TMSFMXList1.ItemHeight := 64; // 关闭动画过渡,减少滚动时的额外绘制 TMSFMXList1.Animation := False;逻辑说明:ItemHeight在虚拟化模式下必须准确,设小了会导致滚动条长度算错,设大了会浪费视口。Animation := False是性能与观感的取舍,数据密集场景建议关。参数上,如果你的项高度不固定(比如有的项带展开详情),虚拟化会失效或表现异常,这时候要么改成固定高度,要么放弃虚拟化改用分页加载。
3.2 动画与过渡的帧率取舍
TMS 控件自带不少过渡动画(展开、切换、弹出)。这些动画在 Windows 上通常没问题,但在低端 Android 设备上可能是掉帧主因。调优思路是:保留交互反馈类动画(点击态、展开),砍掉装饰类动画(背景渐变流动、无意义的淡入淡出)。
具体做法是逐个控件检查动画相关属性,常见的有Animation、Transition、Animate前缀的属性。没有全局一键关闭的后悔药,只能按控件调。我一般会先全关,跑一遍确认帧率达标,再逐个开回来,开到哪个掉帧就停。
// 关闭弹出层的过渡动画 TMSFMXPopup1.Transition := ttNone; // 关闭网格的单元格动画 TMSFMXGrid1.CellAnimations := False; // 保留按钮的点击反馈,这个开销小且体验必要逻辑说明:ttNone是过渡类型枚举里的“无过渡”,比设时长为 0 更彻底。CellAnimations这类属性名在不同控件上可能略有差异,以实际 IDE 属性面板为准。参数上没有统一最优值,取决于目标设备的下限——如果你的用户里有三年前的千元机,就按那个标准调。
3.3 数据绑定的更新频率控制
TMS 控件支持直接绑定数据集或对象列表。绑定本身很方便,但更新频率失控会拖垮界面。典型翻车场景:后台线程每秒多次更新数据源,每次更新都触发控件重绘,界面直接卡死。
控制手段有两个:一是用BeginUpdate/EndUpdate包住批量修改,二是降低刷新频率,比如把实时刷新改成定时器每 500ms 合并刷新一次。
// 批量更新前挂起重绘 TMSFMXGrid1.BeginUpdate; try // 这里做批量数据修改,不会触发逐次重绘 for i := 0 to DataList.Count - 1 do TMSFMXGrid1.Cells[0, i] := DataList[i].Name; finally // 无论是否异常都要恢复重绘,否则界面永久冻结 TMSFMXGrid1.EndUpdate; end;逻辑说明:try...finally是必须的,如果中间抛异常而没调EndUpdate,控件会一直处于挂起状态,表现为界面“死了”,这是血泪经验。参数上,BeginUpdate可以嵌套,但EndUpdate次数要匹配,不匹配同样出问题。
4. 避坑与排查:TMS FMX UI Pack 在 D10.4 上最常见的 5 个翻车现场
4.1 控件面板不出现或包加载失败
现象:编译安装都提示成功,但 Tool Palette 里找不到 TMS 分类,或者重启 IDE 后消失。原因通常是设计期包没有真正注册,或者运行时包路径不在 IDE 的搜索路径里。解决:打开 IDE 的 Component → Install Packages,确认设计期包在列表里且勾选;再检查 Library Path 是否包含运行时包的 dcpu 输出目录。如果还不行,删掉包对应的 dcpu 和 bpl 重新编译,别在旧产物上反复 Install。
4.2 样式不生效但也不报错
现象:设了StyleLookup,界面毫无变化,也没有异常。原因几乎都是样式名写错,或者 StyleBook 没加载对应资源。解决:先在设计期通过属性面板的下拉列表选样式名,别手敲;确认 StyleBook 的Resource已加载且包含该键。如果用的是全局 StyleBook,检查窗体是否真的引用了它。
4.3 移动端编译报缺少单元
现象:Win32 编译通过,切到 Android 编译时报找不到某单元。原因是部分单元有条件编译指令,只对特定平台生效,或者移动端需要额外的库文件。解决:检查报错单元是否在库的移动端目录里,确认 Library Path 对移动平台单独配置了路径。D10.4 的 Library Path 是分平台的,Win32 配了不代表 Android 配了,这点极易忽略。
4.4 虚拟化列表滚动时内容错乱
现象:开启虚拟化后,滚动时某些行显示的是别的行的内容。原因是项复用逻辑与你的自定义绘制或数据绑定冲突,常见于在项上直接挂控件并手动改属性的写法。解决:改用控件的OnGetItemText或数据绑定机制,让内容由数据驱动而非手动设置;如果必须手动,确保在项被复用时重置所有可变属性。
4.5 主题切换后部分控件样式残留
现象:运行时切换主题,大部分控件变了,个别控件还是旧样式。原因是这些控件的StyleLookup被显式设过,优先级高于全局主题。解决:切换主题前,把需要跟随全局的控件的StyleLookup清空或设为默认值,再应用新主题。这个坑在需要“白天/夜间模式”切换的产品里特别常见。
5. 进阶技巧:用 TMS FMX UI Pack 做可维护的主题切换与自定义绘制
走到这一步,基本功能已经能跑了,真正拉开差距的是两件事:主题切换不残留、自定义绘制不拖性能。
先说主题切换的可维护做法。不要在每个窗体里散落StyleLookup赋值,而是集中管理:定义一个主题管理器,切换时遍历窗体上的控件,按类型批量设置样式键。这样新增窗体时只要挂上管理器,不用逐个控件配。
procedure TThemeManager.ApplyTheme(ARoot: TComponent; const ATheme: string); var i: Integer; C: TControl; begin for i := 0 to ARoot.ComponentCount - 1 do begin if ARoot.Components[i] is TControl then begin C := TControl(ARoot.Components[i]); // 只处理显式标记为跟随主题的控件 if C.Tag = TAG_FOLLOW_THEME then ApplyStyleByType(C, ATheme); end; end; end;逻辑说明:用Tag做标记位,避免误改不该动的控件;ApplyStyleByType内部按控件类名映射到对应主题的样式键。参数上,TAG_FOLLOW_THEME是个自定义常量,选一个业务里不会用到的值。这个做法的代价是需要在设计期给控件打 Tag,但换来的是切换逻辑集中、可测试。
再说自定义绘制。TMS 控件大多暴露了OnPaint或OnDrawItem类事件,允许你在默认绘制之上叠加内容。性能原则只有一条:绘制回调里只做绘制,不做数据查询、不做字符串拼接、不创建对象。需要的数据提前算好缓存,回调里直接取。
procedure TForm1.TMSFMXGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; const ARect: TRectF; var ADefaultDraw: Boolean); begin // 只对特定列做自定义,其余走默认绘制 if ACol <> 2 then Exit; // 从预计算缓存取颜色,不在回调里查数据库 Canvas.Fill.Color := FCellColorCache[ARow]; Canvas.FillRect(ARect, 4, 4, AllCorners, 1); ADefaultDraw := False; // 告诉控件本单元格已自绘 end;逻辑说明:ADefaultDraw := False是告诉控件“这个单元格我画完了,你别再画”,漏了这行会出现文字重叠。FCellColorCache是在数据变更时预计算好的数组,回调里只读。参数上,FillRect的圆角参数按视觉稿调,但别在回调里做复杂路径计算,那是帧率杀手。
最后说一个我自己的习惯:每次升级 TMS FMX UI Pack 的小版本前,先在一个独立分支上跑一遍全部窗体的截图对比,重点看列表、网格、弹窗三类控件。因为样式体系的改动往往不体现在编译错误上,而是体现在“看起来差不多但间距差 2px”这种地方,等合并到主干再发现就晚了。这套库能显著缩短界面开发周期,但它不是零成本的银弹,样式体系和虚拟化这两块该花的调试时间省不掉。希望帮到你。
本文还有配套的精品资源,点击获取