Delphi FireMonkey下ScaledLayout多余线条及ImageList问题如何修复
Delphi FMX ImageList 缩放多余线条修复方案
问题说明
该bug在Delphi 10.3、10.4版本均可复现,表现为ScaledLayout缩放后,关联ImageList的菜单/控件边缘出现异常多余线条,更换更大尺寸的图标无法解决,属于ImageList原生实现问题。
原始尺寸界面:
全屏界面:
最小复现代码
unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.ImageList, FMX.ImgList, FMX.Menus, FMX.Objects, FMX.Layouts; type TForm1 = class(TForm) Image1: TImage; PopupMenu1: TPopupMenu; MenuItem1: TMenuItem; ImageList1: TImageList; MenuItem2: TMenuItem; MenuItem3: TMenuItem; MenuItem4: TMenuItem; ScaledLayout1: TScaledLayout; procedure Image1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.Image1Click(Sender: TObject); begin PopupMenu1.Popup(Image1.Position.X,Image1.Position.Y); end; end.
修复方案
- 方案1:图标预处理(无代码改动)
给所有导入ImageList的图标边缘预留1px的透明边,同时将ImageList的Width、Height属性设置为比实际使用的图标尺寸大2px,绘制时会自动裁剪掉边缘溢出的采样像素,可快速解决问题。 - 方案2:运行时动态刷新缓存
在PopupMenu的OnPopup事件中加入以下代码,强制刷新ImageList的图标缓存,避免缩放后的缓存异常:
procedure TForm1.PopupMenu1Popup(Sender: TObject); begin ImageList1.Clear; // 此处替换为自身业务的图标加载逻辑,重新加载所有图标 LoadIconsToImageList(ImageList1); end;
- 方案3:源码级根修复
找到Delphi安装目录下的FMX.ImgList.pas文件,复制到你的项目目录下,找到TImageList.Draw方法中绘制纹理的代码段,将绘制坐标整体偏移0.5像素,避免亚像素采样导致的边界溢出,修改完成后重新编译项目即可,该方案可以彻底解决同类型的ImageList缩放线条问题。 - 方案4:控件替换
使用Delphi 10.3及以上版本自带的TImageCollection替代原生TImageList存储图标,该控件对多DPI、缩放场景的适配做了优化,不会出现该边界线条问题,原有业务代码只需做少量调整即可适配。
内容的提问来源于stack exchange,提问作者Wellington Telles Cunha
相关产品推荐
相关产品推荐

