【Delphi】开发IOS 程序,TLabel 中英文字对齐(水平),一行代码解决显示对齐问题!

目录

一、问题现象:

二、解决方案(一行代码解决ios对齐问题):

三、解决后效果:

四、后记:


一、问题现象:

        在用 Delphi 开发ios程序时,使用TLabel控件显示,会出现中英文无法水平对齐,英文字符会靠上大概少半行,看起来很不协调。

        如下图所示:

        出现这样的问题,从 ios 9 开始就一直存在。目前测试的11.3仍然存在这个问题!所以特写出此解决方案,以方便需要的朋友!

二、解决方案(一行代码解决ios对齐问题):

        由于 Delphi 的版本比较多,不同的版本解决方案基本一致,但都是需要修该对应版本的FMX.FontGlyphs.iOS.pas文件。如果默认安装,一般该文件位于C:\Program Files (x86)\Embarcadero\Studio\22.0\source\fmx目录下,注意22.0表示版本,不同的版本这个数字不一样。

  1. 找到 FMX.FontGlyphs.iOS.pas 这个文件;
  2. 将该文件拷贝到你的工程文件目录下(也就是你正在开发的工程文件);
  3. 修改拷贝后的 FMX.FontGlyphs.iOS.pas 文件;

        本文使用的是D11.3版本,修改 FMX.FontGlyphs.iOS.pas 这个文件中的这个过程 GetDefaultBaseline 。就是修改205行,将 Chars := 'a'; 修改为 Chars := '中';

重点:

        在工程文件中引用修改后的 FMX.FontGlyphs.iOS.pas 文件。

  {$IFDEF  IOS}
      FMX.FontGlyphs.iOS,    //IOS 对齐
  {$ENDIF}

修改前文件

{*******************************************************}
{                                                       }
{             Delphi FireMonkey Platform                }
{ Copyright(c) 2012-2023 Embarcadero Technologies, Inc. }
{              All rights reserved                      }
{                                                       }
{*******************************************************}unit FMX.FontGlyphs.iOS;interface{$SCOPEDENUMS ON}usesSystem.Math, System.Types, System.Classes, System.SysUtils, System.UITypes, System.UIConsts, System.Generics.Collections,System.Generics.Defaults, Macapi.ObjectiveC, Macapi.CoreFoundation, iOSapi.CocoaTypes, iOSapi.CoreGraphics,iOSapi.Foundation, iOSapi.CoreText, iOSapi.UIKit, FMX.Types, FMX.Surfaces, FMX.FontGlyphs;typeTIOSFontGlyphManager = class(TFontGlyphManager)constBoundsLimit = $FFFF;privateFColorSpace: CGColorSpaceRef;FFontRef: CTFontRef;FColoredEmojiFontRef: CTFontRef;FDefaultBaseline: Single;FDefaultVerticalAdvance: Single;procedure GetDefaultBaseline;function GetFontDescriptor: CTFontDescriptorRef;function CGColorCreate(const AColor: TAlphaColor): CGColorRef;function CTFrameCreate(const APath: CGMutablePathRef; const ACharacter: string): CTFrameRef;protectedprocedure LoadResource; override;procedure FreeResource; override;function DoGetGlyph(const ACharacter: UCS4String; const Settings: TFontGlyphSettings;const UseColorfulPalette: Boolean): TFontGlyph; override;function DoGetBaseline: Single; override;function IsColorfulCharacter(const ACharacter: UCS4String): Boolean; override;publicconstructor Create;destructor Destroy; override;end;implementationusesSystem.Character, System.Math.Vectors, Macapi.Helpers, FMX.Graphics, FMX.Consts, FMX.Utils;//........ 此处省略了代码procedure TIOSFontGlyphManager.GetDefaultBaseline;
varChars: string;Str: CFStringRef;Frame: CTFrameRef;Attr: CFMutableAttributedStringRef;Path: CGMutablePathRef;Bounds: CGRect;FrameSetter: CTFramesetterRef;// MetricsLine: CTLineRef;Lines: CFArrayRef;Runs: CFArrayRef;Run: CTRunRef;Ascent, Descent, Leading: CGFloat;BaseLinePos: CGPoint;
beginPath := CGPathCreateMutable();Bounds := CGRectMake(0, 0, BoundsLimit, BoundsLimit);CGPathAddRect(Path, nil, Bounds);Chars := 'a';Str := CFStringCreateWithCharacters(kCFAllocatorDefault, PChar(Chars), 1);Attr := CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);CFAttributedStringReplaceString(Attr, CFRangeMake(0, 0), Str);CFAttributedStringBeginEditing(Attr);try// Fontif FFontRef <> nil thenCFAttributedStringSetAttribute(Attr, CFRangeMake(0, 1), kCTFontAttributeName, FFontRef);finallyCFAttributedStringEndEditing(Attr);end;FrameSetter := CTFramesetterCreateWithAttributedString(CFAttributedStringRef(Attr));CFRelease(Attr);Frame := CTFramesetterCreateFrame(FrameSetter, CFRangeMake(0, 0), Path, nil);CFRelease(FrameSetter);CFRelease(Str);// MetricsLines := CTFrameGetLines(Frame);Line := CTLineRef(CFArrayGetValueAtIndex(Lines, 0));Runs := CTLineGetGlyphRuns(Line);Run := CFArrayGetValueAtIndex(Runs, 0);CTRunGetTypographicBounds(Run, CFRangeMake(0, 1), @Ascent,  @Descent, @Leading);CTFrameGetLineOrigins(Frame, CFRangeMake(0, 0), @BaseLinePos);FDefaultBaseline := BoundsLimit - BaseLinePos.y;FDefaultVerticalAdvance := FDefaultBaseline + Descent;CFRelease(Frame);CFRelease(Path);
end;//........ 此处省略了代码

修改后文件

{*******************************************************}
{                                                       }
{             Delphi FireMonkey Platform                }
{ Copyright(c) 2012-2023 Embarcadero Technologies, Inc. }
{              All rights reserved                      }
{                                                       }
{*******************************************************}unit FMX.FontGlyphs.iOS;interface{$SCOPEDENUMS ON}usesSystem.Math, System.Types, System.Classes, System.SysUtils, System.UITypes, System.UIConsts, System.Generics.Collections,System.Generics.Defaults, Macapi.ObjectiveC, Macapi.CoreFoundation, iOSapi.CocoaTypes, iOSapi.CoreGraphics,iOSapi.Foundation, iOSapi.CoreText, iOSapi.UIKit, FMX.Types, FMX.Surfaces, FMX.FontGlyphs;typeTIOSFontGlyphManager = class(TFontGlyphManager)constBoundsLimit = $FFFF;privateFColorSpace: CGColorSpaceRef;FFontRef: CTFontRef;FColoredEmojiFontRef: CTFontRef;FDefaultBaseline: Single;FDefaultVerticalAdvance: Single;procedure GetDefaultBaseline;function GetFontDescriptor: CTFontDescriptorRef;function CGColorCreate(const AColor: TAlphaColor): CGColorRef;function CTFrameCreate(const APath: CGMutablePathRef; const ACharacter: string): CTFrameRef;protectedprocedure LoadResource; override;procedure FreeResource; override;function DoGetGlyph(const ACharacter: UCS4String; const Settings: TFontGlyphSettings;const UseColorfulPalette: Boolean): TFontGlyph; override;function DoGetBaseline: Single; override;function IsColorfulCharacter(const ACharacter: UCS4String): Boolean; override;publicconstructor Create;destructor Destroy; override;end;implementationusesSystem.Character, System.Math.Vectors, Macapi.Helpers, FMX.Graphics, FMX.Consts, FMX.Utils;//........ 此处省略了代码procedure TIOSFontGlyphManager.GetDefaultBaseline;
varChars: string;Str: CFStringRef;Frame: CTFrameRef;Attr: CFMutableAttributedStringRef;Path: CGMutablePathRef;Bounds: CGRect;FrameSetter: CTFramesetterRef;// MetricsLine: CTLineRef;Lines: CFArrayRef;Runs: CFArrayRef;Run: CTRunRef;Ascent, Descent, Leading: CGFloat;BaseLinePos: CGPoint;
beginPath := CGPathCreateMutable();Bounds := CGRectMake(0, 0, BoundsLimit, BoundsLimit);CGPathAddRect(Path, nil, Bounds);Chars := '中';//Chars := 'a';Str := CFStringCreateWithCharacters(kCFAllocatorDefault, PChar(Chars), 1);Attr := CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);CFAttributedStringReplaceString(Attr, CFRangeMake(0, 0), Str);CFAttributedStringBeginEditing(Attr);try// Fontif FFontRef <> nil thenCFAttributedStringSetAttribute(Attr, CFRangeMake(0, 1), kCTFontAttributeName, FFontRef);finallyCFAttributedStringEndEditing(Attr);end;FrameSetter := CTFramesetterCreateWithAttributedString(CFAttributedStringRef(Attr));CFRelease(Attr);Frame := CTFramesetterCreateFrame(FrameSetter, CFRangeMake(0, 0), Path, nil);CFRelease(FrameSetter);CFRelease(Str);// MetricsLines := CTFrameGetLines(Frame);Line := CTLineRef(CFArrayGetValueAtIndex(Lines, 0));Runs := CTLineGetGlyphRuns(Line);Run := CFArrayGetValueAtIndex(Runs, 0);CTRunGetTypographicBounds(Run, CFRangeMake(0, 1), @Ascent,  @Descent, @Leading);CTFrameGetLineOrigins(Frame, CFRangeMake(0, 0), @BaseLinePos);FDefaultBaseline := BoundsLimit - BaseLinePos.y;FDefaultVerticalAdvance := FDefaultBaseline + Descent;CFRelease(Frame);CFRelease(Path);
end;//........ 此处省略了代码

三、解决后效果:

        已经全部水平对齐,完美解决!

四、后记:

        记得当时在使用D10.1 berlin的时候,就存在这个问题。中间一直在没有用Delphi开发过ios程序,当时以为高版本的Delphi 可能会解决这个问题,没想到D11.3仍然存在这个问题,不知道是否是在什么地方配置下就可以解决(如果确实有知道的请留言告知)。幸好当时解决有记录,今天遇到问题还可以继续使用。这要感谢妈妈教我的:闲时收拾,忙时用!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/160305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WiFi 6的数据在发送端分片和在接收端重组的理解

802.11ax是WiFi 6标准&#xff0c;其引入了一些新的特性和技术来提升无线网络的性能&#xff0c;其中包括帧聚合和帧分片。以下是它们的详细处理流程&#xff1a; 1. 帧聚合 帧聚合是一种提高传输效率的技术&#xff0c;它允许多个数据帧被聚合到一起&#xff0c;然后作为一个…

layui(2.8.18)生成验证码

<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>登入</title><meta name"renderer" content"webkit"><meta http-equiv"X-UA-Compatible" content"IEedge,chrome1&quo…

Go 工具链详解(七):模块缓存清理工具

go mod 缓存 在 Golang 中&#xff0c;模块是对一组版本化的包的集合的描述。Go 1.11 版本引入了模块支持&#xff0c;通过 go mod 命令提供了对模块的管理。Go 模块的一个重要特性是依赖管理&#xff0c;可以清晰地定义项目所依赖的模块及对应的版本&#xff0c;并确保代码使…

电磁优化的并行空间映射方法

空间映射(SM)是一种公认的加速电磁优化的方法。现有的SM方法大多基于顺序计算机制。本文提出了一种用于电磁优化的并行SM方法。在该方法中&#xff0c;每次迭代开发的代理模型被训练以同时匹配多个点的精细模型。多点训练和SM使代理模型在比标准SM更大的邻域内有效。本文提出的…

[补题记录] Complete the Permutation(贪心、set)

URL&#xff1a;https://codeforces.com/group/OcmZ7weh45/contest/487583/problem/J 目录 Problem/题意 Thought/思路 Code/代码 Problem/题意 给出一个长度为 N 的序列&#xff0c;其中的元素都是奇数。 现在要求在两个奇数之间插入一个偶数&#xff0c;使得这三个数递增…

信息压缩模型在自然语言处理中的应用和探讨

信息压缩模型在自然语言处理中的应用和探讨 摘要:正文:结论:附录:摘要: 随着人工智能和深度学习的发展,自然语言处理(NLP)在信息处理中的角色变得越来越重要。然而,海量的自然语言数据为信息处理带来了挑战——更多的信息通常意味着更高的处理成本,并可能导致效率降低。为…

一个工具让你明白“万丈高楼平地起”,拒绝重复造轮子!

大家在公司工作当中是不是很多时间装环境很麻烦&#xff0c;一个项目要上线了&#xff0c;开始网上搜了一边又一遍的环境搭建教程&#xff1f;等到下一个项目要上线了&#xff0c;又上网上搜了一边又一遍的环境搭建教程。关键天花乱坠的互联网&#xff0c;找不到很靠谱的呀。有…

数组的移动

设计程序&#xff0c;给定包含N个整数的数组array&#xff0c;实现操作&#xff1a;前面各个整数顺序向后移动m个位置&#xff0c;最后的m个整数移动到最前面。方法&#xff1a;void move(int array[], int n,int m ) 输入要求 第一行输入两个整数N(1<N<1e6)和m(0<m&…

webpack 配置

1、基础配置 // node js核心模塊 const path require(path) // 插件是需要引入使用的 const ESLintPlugin require(eslint-webpack-plugin) // 自动生成index.html const HtmlWebpackPlugin require(html-webpack-plugin); // 将css文件单独打包&#xff0c;在index.html中…

如何做好项目管理?年薪百万项目大佬一直在用这11张图

大家好&#xff0c;我是老原。 日常工作中&#xff0c;我们会遇到各种大大小小的工作项目&#xff0c;如何能让项目保质保量的完成&#xff0c;是我们项目经理的目标。 项目管理的流程可以说是由一系列的子过程组成的&#xff0c;它是一个循序渐进的过程&#xff0c;所以不能…

python数字

目录 整数&#xff08;如&#xff0c;2、4、20 &#xff09;的类型是 int&#xff0c;带小数&#xff08;如&#xff0c;5.0、1.6 &#xff09;的类型是 float。 Python 用 ** 运算符计算乘方 1&#xff1a; 等号&#xff08;&#xff09;用于给变量赋值。 解释器像一个简单…

进程API

linux下进程的api forkwaitexec fork #include <stdio.h> #include <stdlib.h> #include <unistd.h>/* linux环境运行 子进程并不是完全拷贝了父进程。具体来说&#xff0c;虽然它拥有自己的 地址空间&#xff08;即拥有自己的私有内存&#xff09;、寄存器…

【Delphi】使用TWebBrowser执行JavaScript命令传入JSON参数执行出错解决方案

目录 一、问题背景&#xff1a; 二、实际示例&#xff1a; 三、解决方案&#xff1a; 1. Delphi 代码&#xff1a; 2. javaScript代码&#xff1a; 一、问题背景&#xff1a; 在用Delphi开发程序&#xff0c;无论是移动端还是PC端&#xff0c;都可以很方便的使用TWebBrows…

Postman如何使用(一):导入导出和发送请求查看响应

一、Postman如何导入导出打包的应用 在Postman中导入导出我们的 测试数据包 和 工作环境 非常的方便&#xff1a; 导出数据包的方法如下&#xff1a; 如果你想学习自动化测试&#xff0c;我这边给你推荐一套视频&#xff0c;这个视频可以说是B站播放全网第一的自动化测试教程…

七天.NET 8操作SQLite入门到实战 - 第三天SQLite快速入门

前言 今天我们花费一个小时快速了解SQLite数据类型、SQLite常用命令和语法。 七天.NET 8操作SQLite入门到实战详细教程 第一天 SQLite 简介第二天 在 Windows 上配置 SQLite环境 EasySQLite项目源码地址 GitHub地址&#xff1a;https://github.com/YSGStudyHards/EasySQLite&…

第一百七十六回 如何创建渐变色边角

文章目录 1. 概念介绍2. 实现方法3. 代码与细节3.1 示例代码3.2 代码细节 4. 内容总结 我们在上一章回中介绍了"如何创建放射形状渐变背景"相关的内容&#xff0c;本章回中将介绍"如何创建渐变色边角".闲话休提&#xff0c;让我们一起Talk Flutter吧。 1.…

2023-11-22 LeetCode每日一题(网格中的最小路径代价)

2023-11-22每日一题 一、题目编号 2304. 网格中的最小路径代价二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的整数矩阵 grid &#xff0c;矩阵大小为 m x n &#xff0c;由从 0 到 m * n - 1 的不同整数组成。你可以在此矩阵中&#xff0c;从一个…

一石激起千层浪,有关奥特曼被炒的消息引发了一场热烈的讨论

在毫无征兆的情况下&#xff0c;OpenAI CEO山姆-奥特曼被炒了。 一石激起千层浪&#xff0c;有关奥特曼被炒的消息引发了一场热烈的讨论。 有人将其看成是一场「宫斗」&#xff0c;有人将其看成是OpenAI的董事会与创始人们的一次纠偏。 无论如何&#xff0c;这样一件看似并无…

网工内推 | 合资公司网工,CCNP/HCIP认证优先,朝九晚六

01 中企网络通信技术有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、按照工作流程和指引监控网络运行情况和客户连接状况&#xff1b; 2、确保各监控系统能正常运作&#xff1b; 3、快速响应各个网络告警事件&#xff1b; 4、判断出网络故障&#xff0c;按…