之前写过一个PC端编写Android游戏界面的工具,用以实现VisualStudio般拖拖拽拽设计界面的体验。但是字符串绘制一直不完美,导致并不能完全的“所见即所得”。
起初我以为Android默认字库跟微软雅黑一样(看上去很像),于是在C#里使用微软雅黑,但总对齐不准确,样式也有细微偏差,与真机效果有一定差距。百度才知道Android用的是谷歌自己的“Droid Sans Fallback”字体(百度可下载TTF文件)。
C#中使用自定义字库的方法:
PrivateFontCollection privateFonts = new PrivateFontCollection();
string fileName = "\\DroidSansFallback.ttf";
privateFonts.AddFontFile(fileName);
font = new Font(privateFonts.Families[0], DEFAULT_TEXT_SIZE, FontStyle.Regular, GraphicsUnit.Pixel);
这里注意一定要设置 GraphicsUnit.Pixel(基于像素的度量单位),否则与真机字号有区别。
C#下使用这个字体绘制字符串以后,样式基本一模一样了,但是对齐还是有偏差。
高度偏差的原因是,Android下不是简单地从哪个锚点绘制字符串,还是从基线(baseline)开始绘制,所以计算绘制位置的时候要同时考虑字符串的像素高度以及基线位置。如下图所示:
而C#里GDI绘制貌似没基线这一说。
补充一下,Android里获得字符串实际像素高度并不是简单地得到字号,而是通过上图的ascent、descent等属性计算得到:
FontMetrics fm = paint.getFontMetrics();
float textPxHeight = Math.ceil(fm.descent - fm.ascent);
至于宽度偏差,C#下GDI绘制字符串,默认是有字间距的(经测试大概1.2px),而Android不存在。C#并不提供直接的API设置字间距,我尝试使用GDI32.DLL设置但是失败了。这个问题导致我下C#工具下预览的效果与真机左右大概相差几个像素,暂时只有通过偏移解决了。
最后效果,与真机几乎一样了:
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。