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

news2025/1/12 20:05:23

目录

一、问题现象:

二、解决方案(一行代码解决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}

uses
  System.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;

type
  TIOSFontGlyphManager = class(TFontGlyphManager)
  const
    BoundsLimit = $FFFF;
  private
    FColorSpace: 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;
  protected
    procedure 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;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

uses
  System.Character, System.Math.Vectors, Macapi.Helpers, FMX.Graphics, FMX.Consts, FMX.Utils;

//........ 此处省略了代码

procedure TIOSFontGlyphManager.GetDefaultBaseline;
var
  Chars: string;
  Str: CFStringRef;
  Frame: CTFrameRef;
  Attr: CFMutableAttributedStringRef;
  Path: CGMutablePathRef;
  Bounds: CGRect;
  FrameSetter: CTFramesetterRef;
  // Metrics
  Line: CTLineRef;
  Lines: CFArrayRef;
  Runs: CFArrayRef;
  Run: CTRunRef;
  Ascent, Descent, Leading: CGFloat;
  BaseLinePos: CGPoint;
begin
  Path := 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
    // Font
    if FFontRef <> nil then
      CFAttributedStringSetAttribute(Attr, CFRangeMake(0, 1), kCTFontAttributeName, FFontRef);
  finally
    CFAttributedStringEndEditing(Attr);
  end;

  FrameSetter := CTFramesetterCreateWithAttributedString(CFAttributedStringRef(Attr));
  CFRelease(Attr);

  Frame := CTFramesetterCreateFrame(FrameSetter, CFRangeMake(0, 0), Path, nil);
  CFRelease(FrameSetter);
  CFRelease(Str);

  // Metrics
  Lines := 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}

uses
  System.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;

type
  TIOSFontGlyphManager = class(TFontGlyphManager)
  const
    BoundsLimit = $FFFF;
  private
    FColorSpace: 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;
  protected
    procedure 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;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

uses
  System.Character, System.Math.Vectors, Macapi.Helpers, FMX.Graphics, FMX.Consts, FMX.Utils;

//........ 此处省略了代码

procedure TIOSFontGlyphManager.GetDefaultBaseline;
var
  Chars: string;
  Str: CFStringRef;
  Frame: CTFrameRef;
  Attr: CFMutableAttributedStringRef;
  Path: CGMutablePathRef;
  Bounds: CGRect;
  FrameSetter: CTFramesetterRef;
  // Metrics
  Line: CTLineRef;
  Lines: CFArrayRef;
  Runs: CFArrayRef;
  Run: CTRunRef;
  Ascent, Descent, Leading: CGFloat;
  BaseLinePos: CGPoint;
begin
  Path := 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
    // Font
    if FFontRef <> nil then
      CFAttributedStringSetAttribute(Attr, CFRangeMake(0, 1), kCTFontAttributeName, FFontRef);
  finally
    CFAttributedStringEndEditing(Attr);
  end;

  FrameSetter := CTFramesetterCreateWithAttributedString(CFAttributedStringRef(Attr));
  CFRelease(Attr);

  Frame := CTFramesetterCreateFrame(FrameSetter, CFRangeMake(0, 0), Path, nil);
  CFRelease(FrameSetter);
  CFRelease(Str);

  // Metrics
  Lines := 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.coloradmin.cn/o/1240475.html

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

相关文章

《工程测量学》笔记/期末复习资料

水平角观测方法&#xff1a; ①测回法&#xff1b;②方向观测法&#xff08;全圆观测法&#xff09;。 比例尺精度&#xff1a; 图上0.1mm&#xff08;肉眼能够识别的最小距离&#xff09;所表示的实地距离称为“比例尺精度”。 ①尺寸小于比例尺精度的地物不需要测量&…

部署jekins遇到的问题

jdk问题 我用的jdk版本是21的结果版本太新了&#xff0c;启动jekins服务的时候总是报错最后在jekins的安装目录下面的jekinsErr.log查看日志发现是jdk问题最后换了一个17版本的就解决了。 unity和jekins jekins和Git源码管理 jekins和Git联动使用 我想让jekins每次打包的时…

SpringMVC(五)SpringMVC的视图

SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户 SpringMVC视图的种类很多&#xff0c;默认有转发视图(InternalResourceView)和重定向视图(RedirectView) 当工程引入jstl的依赖&#xff0c;转发视图会自动转换为JstlV…

鸿蒙4.0开发笔记之ArkTs语言基础与基本组件结构(四)

文章声明&#xff1a;本文关于HarmonyOS系统的部分内容和描述借鉴于华为官网的“HarmonyOS开发者学堂”&#xff0c;有需要的也可以进入官网查看。<HarmonyOS第一课>ArkTS开发语言介绍 一、ArkTs语言介绍 ArkTS是鸿蒙系统&#xff08;HarmonyOS&#xff09;优选的主力应…

竞赛 : 题目:基于深度学习的水果识别 设计 开题 技术

1 前言 Hi&#xff0c;大家好&#xff0c;这里是丹成学长&#xff0c;今天做一个 基于深度学习的水果识别demo 这是一个较为新颖的竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/pos…

【机器学习】Nonlinear Independent Component Analysis - Aapo Hyvärinen

Linear independent component analysis (ICA) x i ( k ) ∑ j 1 n a i j s j ( k ) for all i 1 … n , k 1 … K ( ) x_i(k) \sum_{j1}^{n} a_{ij}s_j(k) \quad \text{for all } i 1 \ldots n, k 1 \ldots K \tag{} xi​(k)j1∑n​aij​sj​(k)for all i1…n,k1…K()…

如何访问linux上的web服务

1.获取服务运行端口 例如8080 2.如果时vmware 需要先配置转发端口和主机ip 主机ip需要未使用的 例如&#xff1a; 3.查看虚拟机防火墙设置 centos8 为例 &#xff1a; firewall-cmd --zonepublic --list-ports 查看放通端口 如果没有放通 firewall-cmd --zonepublic --add-p…

使用Pytorch从零开始构建CGAN (conditional GAN)

GAN和DCGAN生成随机图像。因此&#xff0c;我们几乎无法控制生成哪些图像。然而&#xff0c;CGAN 可以让我们指定一个条件&#xff0c;以便我们可以告诉它要生成哪些图像。诀窍是使用可学习层将标签值转换为特征向量&#xff0c;以便生成器可以学习要生成什么图像。鉴别器还利用…

时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测

时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现BiLSTM-Adaboost…

【OpenCV实现图像:使用OpenCV进行图像处理之透视变换】

文章目录 概要计算公式举个栗子实际应用小结 概要 透视变换&#xff08;Perspective Transformation&#xff09;是一种图像处理中常用的变换手段&#xff0c;它用于将图像从一个视角映射到另一个视角&#xff0c;常被称为投影映射。透视变换可以用于矫正图像中的透视畸变&…

ChatGPT规模化服务的经验与教训

2022年11月30日&#xff0c;OpenAI发布ChatGPT&#xff0c;以很多人未曾预料的速度迅速走红。与此同时&#xff0c;由于短时间内用户量的暴涨&#xff0c;导致服务器过载&#xff0c;迫使OpenAI停止新用户的注册。 ChatGPT发布这一年&#xff0c;同样的情景发生了好几次。在最近…

【追求卓越12】算法--堆排序

引导 前面几节&#xff0c;我们介绍了有关树的数据结构&#xff0c;我们继续来介绍一种树结构——堆。堆的应用场景有很多&#xff0c;比如从大量数据中找出top n的数据&#xff1b;根据优先级处理网络请求&#xff1b;这些情景都可以使用堆数据结构来实现。 什么是堆&#xf…

[论文笔记] Scaling Laws for Neural Language Models

概览: 一、总结 计算量、数据集大小、模型参数量大小的幂律 与 训练损失呈现 线性关系。 三个参数同时放大时,如何得到最佳的性能? 更大的模型 需要 更少的样本 就能达到相同的效果。 </

Doris数据模型的选择建议(十三)

Doris 的数据模型主要分为 3 类&#xff1a;Aggregate、Uniq、Duplicate Aggregate: Doris 数据模型-Aggregate 模型 Uniq&#xff1a;Doris 数据模型-Uniq 模型 Duplicate&#xff1a;Doris 数据模型-Duplicate 模型 因为数据模型在建表时就已经确定&#xff0c;且无法修改…

鸿蒙4.0开发笔记之DevEco Studio页面操作router的pushUrl页面跳转与back返回上一页(五)

一、认识组件 关于HarmonyOS中ArkTS的基础组件请参见文章鸿蒙4.0开发笔记之ArkTs语言基础与基本组件结构&#xff08;四&#xff09; 二、实现页面跳转pushUrl 1、操作说明 实现页面跳转的核心便是router.pushUrl的调用&#xff0c;操作起来也很简单&#xff0c;总共就四步…

CSDN等级权益概览

文章目录 一、[权益概览](https://blog.csdn.net/SoftwareTeacher/article/details/114499372)二、权益详情&#xff08;更新中...&#xff09;2.1、等级权益2.2、原创保护2.3、推广管理2.4、博客皮肤 一、权益概览 级别对应分数解释权益未定级0这类用户没有做任何贡献。或者曾…

【done+重点】剑指Offer56-I:找出数组中2个只出现1次的整数

力扣&#xff0c;https://leetcode.cn/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/description/ 题目&#xff1a;一个整型数组nums里除两个数字之外&#xff0c;其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n)&#xff0c;空间…

二叉搜索树java实现

顾名思义&#xff0c;二叉搜索树是一棵二叉树&#xff0c;每个节点就是一个对象&#xff0c;这个对象包含属性left、right和parent。left指向节点的左孩子&#xff0c;right指向节点的右孩子&#xff0c;parent指向节点的父节点&#xff08;双亲&#xff09;。如果某个孩子节点…

《安富莱嵌入式周报》第327期:Cortex-A7所有外设单片机玩法LL/HAL库全面上线,分享三款GUI, PX5 RTOS推出网络协议栈,小米Vela开源

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 1、2023 Hackaday大赛胸牌开源 Vectorscope-main.zip (66.83MB) GitHub - Hack-a-Day/Vectorscope: Vectorscope badg…

Android Spannable 使用​注意事项

1、当前示例中间的 "评论"&#xff0c;使用SpannableStringBuilder实现&#xff0c;点击评论会有高亮效果加粗&#xff0c;但再点击其它Bar时无法恢复默认样式。 2、因为SpannableString或SpannableStringBuilder中的效果是叠加的&#xff0c;恢复默认样式需要先移除…