结果:

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. CodeForces 279B Books

    http://codeforces.com/problemset/problem/279/B 题意 :Valera 有很多的空闲时间,所以他决定看书,给出n本书,编号1到n,和看每本书需要的时间,他看 ...

  2. linux MySQL安装配置

    执行下面的命令初始化授权表: ./scripts/mysql_install_db --user=mysql

  3. cocos2d-x 多分辨率适配详解(转载),以前北京团队设计的游戏,也是用这套方案

    http://blog.csdn.net/kyo7552/article/details/17163487 多种分辨率的适配一直都是一个蛋疼的问题,各家公司可能都有自己的一套方案.今天我为大家介绍的是 ...

  4. eclipse中的输入提示怎么设置

    对于大多数的开发人员来说,打代码是一件非常繁琐的事情,eclipse中为我们提供了自动提示的功能,但是默认的提示只有当我们输入小数点后才能出现提示框,那么我们如何设置eclipse,能够让它为我们提示 ...

  5. Oracle10g 回收站及彻底删除table : drop table xx purge

    drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 1.通过查询回收站user_recyclebin获取被删除的表信息, ...

  6. A9系统时钟用外部

     问个笨蛋的问题,,电脑主板的主频是由外部时钟倍频得来,还是内部时钟倍频?? [ARM11]瘋子 2015/5/5 19:08:16 @蓝凌风 [x86]蓝凌 2015/5/5 19:08:25 外部 ...

  7. Microsoft.Data.ConnectionUI.DataConnectionDialog

    MicrosoftVisualStudio里面的资源之数据库连接配置 这个功能的实现主要是用了Microsoft.Data.ConnectionUI.dll和Microsoft.Data.Connec ...

  8. 函数lock_rec_get_nth_bit

    /*********************************************************************//** Gets the nth bit of a rec ...

  9. ASP.NET Identity(处理身份数据存储) 与 OWIN主机(实现katana验证授权)原理概括

    ASP.NET Identity 是4.5中引入的,支持Clamis(声明)式样登陆[即认证和授权分开模式],结合owin可以实现cookie加密等功能. 1.ASP.NET Identity架构框架 ...

  10. UVa 1471 (LIS变形) Defense Lines

    题意: 给出一个序列,删掉它的一个连续子序列(该子序列可以为空),使得剩下的序列有最长的连续严格递增子序列. 分析: 这个可以看作lrj的<训练指南>P62中讲到的LIS的O(nlogn) ...