结果:

1.需要修改DELPHI自身的FMX.FontGlyphs.Android.pas,复制到程序的根目录下(红色部分为修改过的)。

2.字体文件从 C:\Windows\Fonts 直接拷贝到APP程序根目录后改名增加到Deployment即可,要什么字体,就拷贝什么字体。

3.注意字体文件的大小写。

修改后的FMX.FontGlyphs.Android.pas

 {*******************************************************}
{ }
{ Delphi FireMonkey Platform }
{Copyright(c) 2013-2015 Embarcadero Technologies, Inc.}
{ }
{*******************************************************} unit FMX.FontGlyphs.Android; interface {$SCOPEDENUMS ON} uses
FMX.FontGlyphs, Androidapi.JNI.GraphicsContentViewText; type
TAndroidFontGlyphManager = class(TFontGlyphManager)
private
FPaint: JPaint;
//Current metrics
FTop: Integer;
FAscent: Integer;
FDescent: Integer;
FBottom: Integer;
FLeading: Integer;
protected
procedure LoadResource; override;
procedure FreeResource; override;
function DoGetGlyph(const Char: UCS4Char; const Settings: TFontGlyphSettings): TFontGlyph; override;
function DoGetBaseline: Single; override;
public
constructor Create;
destructor Destroy; override;
end; implementation uses
System.Types, System.Math, System.Character, System.Generics.Collections, System.UIConsts, System.UITypes,
System.Classes, System.SysUtils, FMX.Types, FMX.Surfaces, FMX.Graphics, Androidapi.JNI.JavaTypes, Androidapi.Bitmap,
Androidapi.JNIBridge, Androidapi.Helpers,
System.IOUtils;//引入System.IOUtils是为了能够获取Android的各种系统目录 { TAndroidFontGlyphManager } constructor TAndroidFontGlyphManager.Create;
begin
inherited Create;
FPaint := TJPaint.Create;
end; destructor TAndroidFontGlyphManager.Destroy;
begin
FPaint := nil;
inherited;
end; procedure TAndroidFontGlyphManager.LoadResource;
const
BoldAndItalic = [TFontStyle.fsBold, TFontStyle.fsItalic];
var
TypefaceFlag: Integer;
Typeface: JTypeface;
FamilyName: JString;
Metrics: JPaint_FontMetricsInt;
sFontFile: string;//修改加入的
begin
FPaint.setAntiAlias(True);
FPaint.setTextSize(CurrentSettings.Size * CurrentSettings.Scale);
FPaint.setARGB(, , , );
if TOSVersion.Check(, ) then
FPaint.setHinting(TJPaint.JavaClass.HINTING_ON);
//Font
try
FamilyName := StringToJString(CurrentSettings.Family);
if (BoldAndItalic * CurrentSettings.Style) = BoldAndItalic then
TypefaceFlag := TJTypeface.JavaClass.BOLD_ITALIC
else
if TFontStyle.fsBold in CurrentSettings.Style then
TypefaceFlag := TJTypeface.JavaClass.BOLD
else
if TFontStyle.fsItalic in CurrentSettings.Style then
TypefaceFlag := TJTypeface.JavaClass.ITALIC
else
TypefaceFlag := TJTypeface.JavaClass.NORMAL;
{ Fix Begin 修改开始.如果在下载目录中存在跟字体同名的.ttf 文件,那么优先使用 ttf 文件.
我是放在 SD 卡的下载目录中.大家可以按需要任意改这个位置.
甚至也可以放在 Asset 目录中,这样可以打包在 APK 中.}
sFontFile := TPath.GetSharedDownloadsPath + PathDelim + CurrentSettings.Family + '.TTF';
if FileExists(sFontFile) then
Typeface := TJTypeface.JavaClass.createFromFile(StringToJString(sFontFile))
else
begin
sFontFile := TPath.GetSharedDownloadsPath + PathDelim + CurrentSettings.Family + '.ttf';
if FileExists(sFontFile) then
Typeface := TJTypeface.JavaClass.createFromFile(StringToJString(sFontFile))
else
Typeface := TJTypeface.JavaClass.Create(FamilyName, TypefaceFlag);
end;
{ Fix End 修改结束 }
FPaint.setTypeface(Typeface);
try
Metrics := FPaint.getFontMetricsInt;
//
FTop := Metrics.top;
FAscent := Metrics.ascent;
FDescent := Metrics.descent;
FBottom := Metrics.bottom;
FLeading := Metrics.leading;
finally
Metrics := nil;
end;
finally
FamilyName := nil;
Typeface := nil;
end;
end; procedure TAndroidFontGlyphManager.FreeResource;
begin
if FPaint <> nil then
FPaint.reset;
end; function TAndroidFontGlyphManager.DoGetBaseline: Single;
begin
Result := Abs(FAscent);
end; function TAndroidFontGlyphManager.DoGetGlyph(const Char: UCS4Char; const Settings: TFontGlyphSettings): TFontGlyph;
var
Text: JString;
Bitmap: JBitmap;
Canvas: JCanvas;
GlyphRect: TRect;
C, I, J, Width, Height, OriginY: Integer;
Advance: Single;
Bounds: JRect;
GlyphStyle: TFontGlyphStyles;
PixelBuffer: Pointer;
Data: PIntegerArray;
Path: JPath;
PathMeasure: JPathMeasure;
PathLength: Single;
Coords: TJavaArray<Single>;
StartPoint, LastPoint, Point: TPointF;
NewContour, HasStartPoint: Boolean;
begin
Text := StringToJString(System.Char.ConvertFromUtf32(Char));
try
Advance := FPaint.measureText(Text);
Height := Abs(FTop) + Abs(FBottom) + ;
Width := Ceil(Abs(Advance)) + ;
Bounds := TJRect.Create;
try
FPaint.getTextBounds(Text, , Text.length, Bounds);
if Bounds.left < then
Width := Width - Bounds.left;
Bitmap := TJBitmap.JavaClass.createBitmap(Width, Height, TJBitmap_Config.JavaClass.ARGB_);
try
Canvas := TJCanvas.JavaClass.init(Bitmap);
try
if Bounds.left < then
Canvas.drawText(Text, -Bounds.left, -FAscent, FPaint)
else
Canvas.drawText(Text, , -FAscent, FPaint);
finally
Canvas := nil;
end; GlyphStyle := [];
if ((FAscent = ) and (FDescent = )) or not HasGlyph(Char) then
GlyphStyle := [TFontGlyphStyle.NoGlyph];
if TFontGlyphSetting.Path in Settings then
GlyphStyle := GlyphStyle + [TFontGlyphStyle.HasPath]; // For some font sizes Ascent line is below Bounds.top, cuting off part of a glyph.
// Do not use Y-value of the origin point in such cases.
if FAscent > Bounds.top then
OriginY :=
else
OriginY := Abs(FAscent - Bounds.top);
Result := TFontGlyph.Create(TPoint.Create(Bounds.left, OriginY), Advance,
Abs(FAscent) + Abs(FDescent) + Abs(FLeading), GlyphStyle); if (TFontGlyphSetting.Bitmap in Settings) and (HasGlyph(Char) or ((FAscent <> ) or (FDescent <> ))) and
(AndroidBitmap_lockPixels(TJNIResolver.GetJNIEnv, (Bitmap as ILocalObject).GetObjectID, @PixelBuffer) = ) then
begin
Data := PIntegerArray(PixelBuffer);
GlyphRect.Left := Bounds.left;
GlyphRect.Right := Bounds.Right;
GlyphRect.Top := OriginY;
GlyphRect.Bottom := Abs(FAscent - Bounds.bottom); if (GlyphRect.Width > ) or (GlyphRect.Height > ) then
begin
Result.Bitmap.SetSize(GlyphRect.Width + , GlyphRect.Height + , TPixelFormat.BGRA);
if TFontGlyphSetting.PremultipliedAlpha in Settings then
begin
for I := GlyphRect.Top to GlyphRect.Bottom do
Move(Data[I * Width + Max(GlyphRect.Left, )],
Result.Bitmap.GetPixelAddr(, I - GlyphRect.Top)^, Result.Bitmap.Pitch);
end
else
for I := GlyphRect.Top to GlyphRect.Bottom - do
for J := GlyphRect.Left to GlyphRect.Right - do
begin
C := Data[I * Width + J];
if C <> then
begin
C := ((C shr ) and $FF + (C shr ) and $FF + (C and $FF)) div ;
Result.Bitmap.Pixels[J - GlyphRect.Left, I - GlyphRect.Top] := MakeColor($FF, $FF, $FF, C);
end
end;
end;
AndroidBitmap_unlockPixels(TJNIResolver.GetJNIEnv, (Bitmap as ILocalObject).GetObjectID);
end;
//Path
if TFontGlyphSetting.Path in Settings then
try
Path := TJPath.Create;
FPaint.getTextPath(Text, , Text.length, Result.Origin.X, Result.Origin.Y, Path);
PathMeasure := TJPathMeasure.Create;
PathMeasure.setPath(Path, False);
Coords := TJavaArray<Single>.Create();
if PathMeasure.getLength > then
repeat
PathLength := PathMeasure.getLength;
NewContour := True;
HasStartPoint := False;
I := ;
while I < PathLength do
begin
if PathMeasure.getPosTan(I, Coords, nil) then
begin
Point := PointF(Coords[], Coords[]);
if NewContour then
begin
Result.Path.MoveTo(Point);
NewContour := False;
HasStartPoint := False;
end
else
if Point <> LastPoint then
begin
if HasStartPoint and (LastPoint <> StartPoint) then
if not SameValue(((Point.Y - StartPoint.Y) / (Point.X - StartPoint.X)), ((Point.Y - LastPoint.Y) / (Point.X - LastPoint.X)), Epsilon) then
begin
Result.Path.LineTo(Point);
HasStartPoint := False;
end
else
else
Result.Path.LineTo(Point);
end;
LastPoint := Point;
if not HasStartPoint then
begin
StartPoint := Point;
HasStartPoint := True;
end;
end;
Inc(I);
end;
if Result.Path.Count > then
Result.Path.ClosePath;
until not PathMeasure.nextContour;
Point := Result.Path.GetBounds.TopLeft;
Result.Path.Translate(-Point.X + Result.Origin.X, -Point.Y + Result.Origin.Y);
finally
FreeAndNil(Coords);
Path := nil;
PathMeasure := nil;
end;
finally
Bitmap.recycle;
Bitmap := nil;
end;
finally
Bounds := nil;
end;
finally
Text := nil;
end;
end; end.

实例代码:

 unit Unit1;

 interface

 uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls; type
TForm1 = class(TForm)
Label1: TLabel;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation
uses System.IOUtils;
{$R *.fmx}
{$R *.NmXhdpiPh.fmx ANDROID} procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Font.Family := 'STHUPO';
end; procedure TForm1.Button2Click(Sender: TObject);
begin
Label1.Font.Family := 'STLITI';
end; procedure TForm1.FormCreate(Sender: TObject);
var
fontfile, fontfilefrom: string;
begin
//文件名大小写敏感,切记
//这是我们能够引用的字体文件的目标位置:
fontfile := TPath.GetSharedDownloadsPath + PathDelim + 'STHUPO.TTF';
//随程序安装后,字体文件位置,卸载程序时会被删除:
fontfilefrom := TPath.Combine(TPath.GetDocumentsPath, 'STHUPO.TTF');
if FileExists(fontfilefrom) and (not FileExists(fontfile)) then
begin
tfile.Copy(fontfilefrom, fontfile); //将字体文件拷贝到我们设定的目录
end; //文件名大小写敏感,切记
//这是我们能够引用的字体文件的目标位置:
fontfile := TPath.GetSharedDownloadsPath + PathDelim + 'STLITI.TTF';
//随程序安装后,字体文件位置,卸载程序时会被删除:
fontfilefrom := TPath.Combine(TPath.GetDocumentsPath, 'STLITI.TTF');
if FileExists(fontfilefrom) and (not FileExists(fontfile)) then
begin
tfile.Copy(fontfilefrom, fontfile); //将字体文件拷贝到我们设定的目录
end;
end; end.

Android实例-使用自定义字体文件(XE8+小米2)的更多相关文章

  1. Delphi XE5开发Android程序使用自定义字体文件.

    万事大吉,只欠根据字体文件(.ttf文件)切换阅读字体,通常Android系统只带三种以下字体.一般用Java/Eclipse开发的话比较简单,typeface的createFromAsset,cre ...

  2. Android实例-屏幕操持常亮(XE8+小米2)

    相关资料: http://www.bubuko.com/infodetail-163304.html 结果: 1.打开权限Wake lock为True. 第三方单元: unit Android.JNI ...

  3. Android实例-利用WebBrowser实现浏览器(XE8+小米2)

    结果: 1.网络好的情况下,打开很快,很流畅. 2.地址栏真心不好使,如果真要做应用,这块必须自己优化一下. 实例代码: unit Unit1; interface uses System.SysUt ...

  4. Android实例-TRectangle加载图片(XE8+小米2)

    结果: 1.加载图片很流畅,可以做背景用. 2.现在是加载了正形与圆形,其他形状能不能加载呢?自己测试哦,要多动手才行. 3.需要把图片打到包里哦(路径为“assets\internal\”). 实例 ...

  5. Android实例-多窗口的切换(XE8+小米2)

    1.图片一是程序运行后的界面. 2.图片二是点击"非模态显示"的界面. 3.图片三是点击"模诚显示"的界面(提示平台不支持). unit Unit1; inte ...

  6. Android 开发使用自定义字体

    有时候,系统自带的字体并不能满足我们特殊的需求,这时候就需要引用其他的字体了,可以把下载的字体文件放在 assets 目录下. 自定义字体文件不能使用xml代码读取而应该使用java代码: publi ...

  7. Android Studio设置自定义字体

    Android Studio设置自定义字体 (1)进入设置页面,File->Settings (2)自定义字体Editor->Colors&Fonts->Font (3)点击 ...

  8. Android 中使用自定义字体的方法

    1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . <?xml version="1.0 ...

  9. Html 项目使用自定义字体文件问题

    感谢大佬:https://zhidao.baidu.com/question/652711582735059245.html 1.首先在项目过程中新建文件夹fonts将准备好的ttf字体文件复制该文件 ...

随机推荐

  1. tomcat部署javaweb项目的三种方式

    一.将项目文件夹或war包直接拷贝到tomcat的webapps下 二.在Tomcat\conf\Catalina\localhost下建立xml文件 修改内容如下<Context path=& ...

  2. android 从系统相册获取一张图片

    package net.viralpatel.android.imagegalleray; import android.app.Activity; import android.content.In ...

  3. Android 通过http访问服务器

    目前Android 与服务器交互有两种方式:1.Socket 2. Http : 但由于Http的封装性以及性能比socket要好,所以推荐使用http方式和服务器交互: 通过http访问服务器有三种 ...

  4. POJ 1036 Rails 模拟堆栈

    水题,主要是思路清晰,判断明确. 记x为A站最前方的车,y表示下一列要进入B站的车厢,初识时,x=1;y=a1;C=[]; 在调度过程中: if(y==0)那么调度成功,退出模拟过程:否则 if(x= ...

  5. Android studio中不同颜色代表什么意思

    和你的版本控制工具相关 绿色,已经加入控制暂未提交红色,未加入版本控制蓝色,加入,已提交,有改动白色,加入,已提交,无改动

  6. 理解TCP/IP协议

    TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议. 单从TCP/IP协议这个名称看,好多人误 ...

  7. 部分常见ORACLE面试题以及SQL注意事项

    部分常见ORACLE面试题以及SQL注意事项 一.表的创建: 一个通过单列外键联系起父表和子表的简单例子如下: CREATE TABLE parent(id INT NOT NULL, PRIMARY ...

  8. VPN DNS leak 问题的解决

    前一段时间遇到一个问题.customer说发现连接VPN后在PPP端发现security leak,整个转了好大一个圈子才把问题解决了.之所以费这么大周折,倒不是因为很难解决,只是费了很大劲儿才定位了 ...

  9. The only legal comparisons are between two numbers, two strings, or two dates.

    The only legal comparisons are between two numbers, two strings, or two dates. Left  hand operand is ...

  10. UVa 11971 (概率) Polygon

    题意: 有一根绳子,在上面随机选取k个切点,将其切成k+1段,求这些线段能够成k+1边形的概率. 分析: 要构成k+1边形,必须最长的线段小于其他k个线段之和才行. 紫书上给出了一种解法,但是感觉理解 ...