TMS FMX UI Pack 3.7.3安装避坑与实践:从网格到HTML欢迎页
简介TMS FMX UI Pack 3.7.3.0是一套面向Delphi开发者的FireMonkey跨平台UI组件库覆盖XE7到10.4 Sydney等多个版本打包了完整源码与Demo示例适合需要构建原生跨平台界面的中高级Delphi程序员。压缩包内含1410个文件以pas源码文件与dcu编译单元为主体另有fmx界面定义、dproj工程文件、style样式资源以及PDF、CSV等说明文档总大小约58.28MB。其中pas为原始代码dcu为编译后单元fmx为可视化界面style为样式定义各类型相互配合便于二次定制。已有576人浏览学习获得初步验证。开发者既能直接读取各组件实现并运行设计期Demo也能利用样式文件快速调整界面外观同时多语言拼写检查词典等附加文件让本地化开发更省力对希望深究TMS FMX封装原理、扩充自定义控件库的人而言是难得的参考素材。1. 拿到安装包之后先别急着点Setup先说结论TMS FMX UI Pack 3.7.3.0 for D10.4这套组件库不是那种装上就能用得爽的东西。如果直接一路Next装完就开干头一个小时大概率会浪费在跟IDE较劲上。我在拿到这个版本的第一时间是先看了Release Notes。3.7.3.0对应的Delphi 10.4 Sydney分支TMS官方对D10.4的支持周期其实已经进入了维护尾声这个版本更像是给10.4用户的一个稳定性快照把前面几个小版本累积的控件bug修了一遍同时适配了10.4.2的更新包。如果你用的是10.4.0或者10.4.1安装时会遇到IDE版本检测的提示但这不是致命错误后面我会说怎么绕过去。安装这套包之前有两个前置条件需要确认第一FMX框架已经在IDE里装好也就是安装Delphi时勾选了FireMonkey支持第二项目的Target Platform里至少有Windows 64位或Android的SDK配置好。这两个条件缺一个组件安装成功也会在编译期报一堆找不到平台单元的错很容易让人误以为是组件包本身的问题。安装包本身体积不小里面包含了设计期包和运行期包两套DCU。TMS的安装程序支持勾选具体组件集合我的建议是第一次装的时候全选跑通一个Demo之后再回过头来精简而不是一开始就猜哪些组件用不到然后去掉——因为TMS FMX UI Pack里有些组件存在隐藏依赖比如某些高级编辑框依赖基础绘制库你只装编辑器不装核心库编译直接挂。提示安装路径不要带中文和空格。TMS的IDE插件在注册组件时会写绝对路径路径里有空格虽然大部分情况下能跑但一旦你同时装了多个版本的TMS包路径解析会错乱导致IDE启动时报package not found。装完之后第一步不是新建项目而是打开IDE的Components菜单确认TMS FMX Pack这一组组件是否全部显示在面板里。如果发现某个分类下组件数量明显不对多半是设计期包注册失败重新Build一下安装程序生成的dclusr文件就能解决。2. 版本检测拦截、DCU路径冲突两个最常见的安装事故2.1 D10.4.0/10.4.1用户怎么过版本检测如果你用的是Delphi 10.4.0原版没有打任何Update安装TMS 3.7.3.0时大概率会弹出一个提示框说当前IDE版本低于预期询问是否继续。我见过很多人在这里直接点取消然后去论坛求助其实完全没必要。TMS的安装脚本是通过读取注册表里IDE的版本号来判断的它期望读到10.4.2的版本号但你本地是10.4.0就会触发这个警告。处理方式很简单忽略警告强制继续安装。安装完成后不要急着用先确认两点一是IDE能否正常启动且不报package version mismatch二是新建FMX项目后组件面板里能否正常显示TMS那组控件。如果IDE启动时报了版本冲突说明安装程序往IDE里注册的BPL版本号和你的IDE不匹配这时候去安装目录下找有没有对应10.4.0的预编译BPL目录通常是一个名为10.4.0或D10_4的文件夹手动把里面的BPL拷贝到C:\Users\你的用户名\AppData\Roaming\Embarcadero\BPL下替换即可。2.2 多个Delphi版本共存时的DCU地狱这是我踩过最深的一个坑。机器上同时装了Delphi 10.3和10.4TMS安装程序默认会把DCU按照$(BDSCOMMONDIR)\Dcp这样的公共目录来布局。这本是TMS的贴心设计——多个IDE版本共享同一份源码头文件但DCU和DCP是按平台和编译器版本区分的。问题出在Library Path上10.4的IDE会把10.3的DCU也加入搜索路径结果就是编译时要么提示Unit TMSFMXGrid was compiled with a different version of FMX.Grid要么干脆链接时报一堆重复定义。理解这个问题其实一句话就够了Delphi的DCU和编译器版本强绑定不同版本编译出来的DCU互不通用而TMS安装程序并不会自动帮你区分当前激活的IDE版本去配置Library Path。解决办法是手动检查IDE的Library路径配置在Tools Options Language Delphi Library里把TMS相关的路径全部删除然后重新添加当前IDE版本对应的路径。具体来说安装目录下会有D10.4、D10.3这样的子目录分别对应不同IDE版本的DCU。确保只把D10.4目录加入10.4的搜索路径不要图省事把整个TMS根目录加进去否则又会把其他版本的残留DCU拉进来。2.3 安卓编译器报Resource link failed的排查链路如果你要做Android开发装完TMS后在10.4.2上编译一个最简单的空FMX项目可能一切正常但只要拖入TMS的任意一个组件编译就报Resource link failed: aapt2错误。这个问题的根子不在TMS而在Android SDK的Build Tools版本。TMS FMX UI Pack 3.7.3.0针对Android的RTL运行时库链接逻辑比系统自带组件要求更高它默认使用较新版本的aapt2来处理资源压缩。而Delphi 10.4自带的SDK配置里Build Tools版本往往偏低导致aapt2崩溃。排查链路是这样的先打开SDK Manager确认Build Tools版本如果低于30.0.0装一个新的建议30.0.3然后在IDE里把SDK重新指向一次让Delphi重新生成SDK配置文件最后清理一次Android的临时目录C:\Users\用户名\.android\build-cache再编译就正常了。整个过程大概10分钟但如果你不知道这个逻辑会在网上搜到一堆过时的修改aapt2路径的办法改来改去越改越乱。3. 组件库的核心价值拆解哪些组件才是真正的生产力3.1 高频组件真实体验排名这套包里的组件数量非常多粗略数一下大概有几十个覆盖了网格、树形列表、编辑器、按钮、日历、布局、仪表盘等类别。说实话这里面有些组件属于有了更好没有也无所谓但有几个是真正影响开发效率的。我实测下来最值得优先掌握的三个组件是TMSFMXStringGrid字符串网格、TMSFMXTreeView树形视图、以及TMSFMXCollapsiblePanel可折叠面板。TMSFMXStringGrid和原生的TStringGrid相比最大的优势在于它支持虚拟模式和列排序而且滚动流畅度明显更好。拿它来展示大量数据时把Options里的goVirtualMode打开配合OnGetCellData事件按需返回数据即使同时面对几万行记录也不会掉帧。这个逻辑用一句话说就是界面只渲染当前可见的几十行而不是把所有数据都加载进内存用户体验和心理感受完全是两码事。TMSFMXTreeView则解决了FMX原生没有好用的树形控件的问题。它支持多级节点、节点拖拽、选中状态管理、懒加载子节点。做后台管理类App的菜单导航或者做文件浏览器、组织架构图这个控件直接拖上去填数据就行省去了自绘TreeView的繁琐过程。TMSFMXCollapsiblePanel是那种不显眼但真香的组件。移动端App里做筛选条件面板、设置分类、折叠式帮助文档用它比自己在原生Layout上写显隐动画要省太多事。它内部封装了高度动画和内容大小自适应只需要设置Collapsed和AnimateCollapse两个属性剩下交给它。3.2 虚拟网格性能实测数据我在一个实际项目里用TMSFMXStringGrid做了一套设备参数表同时在线约80个设备每个设备有35个参数需要定时刷新。如果用普通Grid直接往Cell里塞字符串每次刷新都要全量重绘帧率会掉到个位数。换成TMSFMXStringGrid的虚拟模式之后我做了如下配置开启Options.GoVirtualMode设置Options.VirtualModeAutoRowHeight : False统一固定行高在OnGetCellData里按需返回实时数据刷新的频率控制在500毫秒一次最终的效果是CPU占用从原来的25%左右降到6%界面滑动和刷新完全同时进行不再碎屏。这个提升的根本原因是虚拟模式大幅减少了FMX的重绘面积不再每秒钟对网格内所有可见单元做对象级别的更新。这套优化思路放到大批量历史数据回放、股票行情展示、IoT设备监控这类场景效果会更加明显。换句话说如果你只在界面上放几十条数据原生Grid就够用了但一旦数据量和刷新频率上来了这个组件的价值就立刻体现出来。3.3 编辑器和布局组件的隐藏价值TMSFMXEdit和TMSFMXMemo这一组编辑器组件除了常规的文字输入还能做到输入时实时格式化、错误提示、水印文字、自定义IME选项。我最常用的能力是水印文字和输入校验提示加水印不需要自绘设一个WatermarkText属性就搞定校验不通过时NotifyStatus(False, 格式不对)就可以在边框或图标上给出视觉反馈。这一套行为在Windows桌面版和安卓版上的观感一致省去了各自维护一套UI逻辑的麻烦。布局方面TMSFMXFlowLayout和TMSFMXGridPanelLayout两个布局组件适合做自适应UI。它们可以自动排列子控件像网格一样对齐做数据看板类和表单类界面很顺手。我在一个报表项目里用TMSFMXGridPanelLayout实现了响应式卡片排列屏幕宽度变化时卡片自动换行不用写任何位置计算代码调试效率提升得非常明显。4. 用HTML组件做动态欢迎界面热搜背后的可行路线最近看到很多人在讨论FMX里使用HTML组件来开发欢迎界面这个思路确实有可取之处。FMX原生做复杂排版和动效的成本比较高但HTML/CSS做这些事情就是老本行所以FMX壳 HTML内芯的混合开发模式正在成为不少人的选择。在TMS FMX UI Pack 3.7.3.0里与HTML相关的主要是两个组件TMSFMXHTMLText和TMSFMXWebBrowser。TMSFMXHTMLText是轻量级的HTML解析渲染组件不支持完整CSS3和JavaScript适合展示富文本内容TMSFMXWebBrowser是重量级浏览器组件基于系统WebView支持完整Web技术和JavaScript交互。4.1 欢迎页场景的选型逻辑做欢迎界面我的建议是先用TMSFMXWebBrowser如果你只需要静态展示TMSFMXHTMLText就够了但如果你想要动态效果、点击交互、或者定时跳转那就需要TMSFMXWebBrowser。典型的实现思路是这样的把欢迎页做成本地HTML文件打包进App的资源目录在Form的OnShow事件里动态加载等待页面加载完成或者设置一个定时器到时间后切换到主界面。以Android为例本地HTML放在assets\internal\welcome.html在Form上用一份代码就能实现跨平台加载。D10.4环境下的代码逻辑大致是procedure TFormWelcome.FormShow(Sender: TObject); var LPath: string; begin TMSFMXWebBrowser1.Visible : True; {$IFDEF ANDROID} LPath : file:///android_asset/welcome.html; {$ELSE} LPath : file:// ExtractFilePath(ParamStr(0)) welcome.html; {$ENDIF} TMSFMXWebBrowser1.URL : LPath; end;用URL属性直接加载本地文件而不是先ReadAllText再LoadHTML好处是本地的CSS和JS引用路径不会乱图片资源也能正常解析。4.2 JavaScript桥接实现点击跳转如果欢迎页上有个立即体验按钮点击之后要跳转到App主页面那就要用到FMX和WebView的JavaScript桥接。TMSFMXWebBrowser提供了一系列事件用于接收来自网页的消息。在HTML里按钮的点击事件这样写button onclickonEnterApp()立即进入/button script function onEnterApp() { JSInterface.onMessage(enter_main); } /scriptJSInterface是WebView暴露给网页的桥接对象但TMSFMXWebBrowser在D10.4里的桥接并不是直接注入一个对象而是通过拦截页面导航的方式实现。具体来说自定义一个协议比如tmsapp://enter_main然后在OnShouldStartLoad事件里拦截并判断procedure TFormWelcome.TMSFMXWebBrowser1ShouldStartLoad(ASender: TObject; const AURL: string; var ACanLoad: Boolean); begin if AURL.StartsWith(tmsapp://) then begin if AURL.Contains(enter_main) then ShowMainForm; ACanLoad : False; end else ACanLoad : True; end;这个方案的逻辑网页端的跳转不再真的去加载一个页面而是把动作编码在URL里传给FMX端处理。好处是绕开了平台差异在Android的WebView和Windows的EdgeWebView2上都能工作不用去折腾不同平台的JavaScript扩展接口。4.3 资源加载与字体问题的避坑用WebBrowser加载本地HTML时最常遇到的一个问题是字体渲染异常。中文环境下如果HTML里没有显式指定中文字体Windows上可能默认用宋体Android上则是系统默认字体两者观感差距大。我的建议是在CSS里做字体回退链body { font-family: PingFang SC, Microsoft YaHei, sans-serif; }在D10.4的FMX环境下TMSFMXWebBrowser在Windows上依赖的是EdgeWebView2运行时。如果你的目标机器没装这个运行时WebBrowser会加载失败或者白屏。要么在部署包里附带WebView2的引导安装程序要么用TMSFMXWebBrowser.CheckWebView2RuntimeAvailable在启动时检测并给出提示。这个组件在iOS上使用的是WKWebViewAndroid上使用的是系统WebView两个平台对本地文件访问的限制不完全一样。iOS上file://协议读取本地HTML包内资源是可以的但如果你想要加载位于Documents目录下的动态生成HTML建议仍配合自定义协议或者直接读取字符串后LoadHTML避免平台限制导致的路径访问被拦截。5. 跨平台部署中的兼容性问题Windows、Android、iOS三端实测5.1 Windows下最容易忽略的DPI问题在Windows上FMX的HighDPI支持本来就比VCL好但TMS的组件并非全部完美适配DPI感知。实测发现TMSFMXStringGrid在4K显示器150%缩放下如果Form的ScaleMode没有设置成ScalingMode.DPI网格内的文字会出现轻微模糊尤其在缩放比例变化之后列宽计算会偏离预期。解决办法是在主Form的OnCreate里显式设置Form1.ScaleMode : TFormScaleMode.ScaleModeDPI;原理很简单DPI模式会按照系统的实际缩放比例重新计算所有FMX组件的虚拟尺寸而ScaleModeOff是钉死在设计时像素高分辨率屏上就会出现设计时很完美、运行时很奇怪的错位感。TMS的多数组件是支持DPI动态缩放的前提是Form先进入DPI模式否则子组件拿到的缩放因子不统一绘制自然就乱了。5.2 Android上的包体与权限注意TMS FMX UI Pack编译后对APK体积的影响取决于用到的组件范围。为了减小体积可以配合Delphi 10.4的单元级裁剪特性在Project Options的Delphi Compiler里勾选Enable unit scope names同时把TMS包的使用限定在需要的单元范围内。实测下来一个只需要网格和树形控件的Android APK裁剪前后体积差能达到3到4MB对移动端来说这个差距在用户下载转化率上的影响值得关注。权限方面TMSFMXWebBrowser在Android上需要INTERNET权限如果你的App里没有其他网络相关功能很容易漏掉。Delphi的Android Manifest模板里默认不会带这个权限需要在Project Options Entitlement List里手动打开Internet。5.3 iOS上的WKWebView白屏问题TMSFMXWebBrowser在iOS上使用WKWebView这个组件有个众所周知的特性加载内容时如果HTML里包含证书无效的远程资源、或者本地文件路径没放到Bundle的根目录下会出现白屏但不报错。这里有个非常实用的排查手段在TMSFMXWebBrowser.OnDidFinishNavigation事件里打印DocumentTitle。如果标题为空说明页面根本没有正常加载完成如果标题有值但界面空白多半是CSS或者JS执行出错。通过这种方式能快速把问题定位在加载层还是渲染层不用靠猜。另外iOS模拟器对WKWebView的JavaScript执行性能远低于真机。在做HTML欢迎页的动画调试时不要在模拟器上判断流畅度同一个页面在模拟器上可能掉帧到30帧真机上却是满帧运行差距非常明显。6. 我对这套组件库的真实评价和后续扩展方向TMS FMX UI Pack 3.7.3.0 for D10.4这个版本放在2024年去看肯定不是TMS家族里最新的但对于D10.4用户来说仍然是一个稳定性很高的选择。我不会拿它去和TMS的下一代产品做简单对比因为每个产品线的定位不一样。它贵在成熟和稳定社区资料全遇到的坑基本都有前人踩过能搜到解决方案这对于一个商用项目选型来说是很重要的加分项。我自己在实际项目里最依赖的还是StringGrid、DataGridView、TreeView这几个高频组件加上WebBrowser做混合界面。这套组合配合下来维护成本和开发效率达到了一个比较舒服的平衡点。最后分享一个小技巧用TMSFMXUI Pack自带的演示工程来快速上手。安装目录下有个Demos文件夹里面按组件分类存放了几十个示例项目。别一个个去翻直接全局搜索你正在用的组件名打开对应的Demo看它是怎么设置属性的然后复制到你的项目里改。这种方式比读文档快得多尤其是那些属性之间联动关系复杂的组件比如Grid的层级分组和Column汇总Demo代码本身就是最好的参考文档。如果后续有条件升级到更新的Delphi版本TMS FMX UI Pack的新版本对D12的WebBrowser组件能力提升非常明显HTML和FMX之间的双向调用会顺畅很多这个是后话了。在D10.4这个平台下充分挖掘3.7.3.0的能力把数据展示、高效布局和轻量混合界面这三件事做扎实已经能覆盖绝大多数FMX项目的UI需求。本文还有配套的精品资源点击获取