带你深入理解 Flutter 中的字体 “冷” 知识

栏目: IT技术 · 发布时间: 4年前

内容简介:本篇将带你深入理解 Flutter 开发过程中关于字体和文本渲染的“冷”知识,帮助你理解和增加关于 Flutter 中字体绘制的“无用”知识点。毕竟此类相关的内容太少了首先从一个简单的文本显示开始,如下代码所示,运行后可以看到界面内出现了一个

本篇将带你深入理解 Flutter 开发过程中关于字体和文本渲染的“冷”知识,帮助你理解和增加关于 Flutter 中字体绘制的“无用”知识点。

毕竟此类相关的内容太少了

首先从一个简单的文本显示开始,如下代码所示,运行后可以看到界面内出现了一个 H 字母,它的  fontSize 是  100Text 被放在一个高度为  200 的  Container 中,然后如果这时候有人问你: Text 显示  H  字母需要占据多大的高度,你知道吗?


@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

alignment: Alignment.center,

child: new Row(

children: <Widget>[

Container(

child: new Text(

"H",

style: TextStyle(

fontSize: 100,

),

),

),

Container(

height: 100,

width: 100,

color: Colors.red,

)

],

),

)


),

),

);

}

带你深入理解 Flutter 中的字体 “冷” 知识

一、TextStyle

如下代码所示,为了解答这个问题,首先我们给 Text 所在的   Container 增加了一个蓝色背景,并增加一个  100 * 100 大小的红色小方块做对比。

@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

alignment: Alignment.center,

child: new Row(

mainAxisAlignment: MainAxisAlignment.center,

children: <Widget>[

Container(

color: Colors.blue,

child: new Text(

"H",

style: TextStyle(

fontSize: 100,

),

),


),

Container(

height: 100,

width: 100,

color: Colors.red,

)

],

),

)


),

),

);

}

结果如下图所示,可以看到 H 字母的上下有着一定的  padding 区域,蓝色 Container 的大小明显超过了  100 ,但是黑色的  H 字母本身并没有超过红色小方块,那蓝色区域的高度是不是  Text 的高度,它的大小又是如何组成的呢?

带你深入理解 Flutter 中的字体 “冷” 知识

事实上,前面的蓝色区域是字体的行高,也就是 line height,关于这个行高,首先需要解释的就是  TextStyle 中的  height 参数。

默认情况下 height 参数是  null ,当我们把它设置为  1 之后,如下图所示,可以看到蓝色区域的高度和红色小方块对齐,变成了  100 的高度,也就是行高变成了  100 ,而  H 字母完整的显示在蓝色区域内。

带你深入理解 Flutter 中的字体 “冷” 知识

height 是什么呢?根据文档可知,首先  TextStyle 中的  height 参数值在设置后,其效果值是  fontSize 的倍数:

  • 当  height 为空时,行高默认是使用字体的 量度 (这个 量度 后面会有解释);
  • height
    height
    fontSize
    

如下图所示,蓝色区域和红色区域的对比就是 height 为  null 和  1 的对比高度。

带你深入理解 Flutter 中的字体 “冷” 知识

另外上图的 BaseLine 也解释了:为什么  fontSize 为 100 的  H 字母,不是充满高度为 100 的蓝色区域。

根据上图的示意效果,在 height 为 1 的红色区域内, H 字母也应该是显示在基线之上,而基线的底部区域是为了如 g 和 j 等字母预留,所以如下图所示,在  Text 内加入 g 字母并打开 Flutter 调试的文本基线显示,由 Flutter 渲染的绿色基线也可以看到符合我们预期的效果。

忘记截图由 g 的了,脑补吧。

带你深入理解 Flutter 中的字体 “冷” 知识

接着如下代码所示,当我们把 height 设置为  2 ,并且把上层的高度为  200 的  Container 添加一个紫色背景,结果如下图所示,可以看到蓝色块刚好充满紫色方块,因为  fontSize 为  100 的文本在  x2 之后恰好高度就是  200

@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

color: Colors.purple,

alignment: Alignment.center,

child: new Row(

mainAxisAlignment: MainAxisAlignment.center,

children: <Widget>[

Container(

color: Colors.blue,

child: new Text(

"Hg",

style: TextStyle(

fontSize: 100,

height: 2,

),

),


),

Container(

height: 100,

width: 100,

color: Colors.red,

)

],

),

)


),

),

);

}

带你深入理解 Flutter 中的字体 “冷” 知识

不过这里的  Hg  是往下偏移的,为什么这样偏移在后面会介绍,还会新的对比。

最后如下图所示,是官方提供的在不同 TextStyle 的  height 参数下,  Text 所占高度的对比情况。

带你深入理解 Flutter 中的字体 “冷” 知识

二、StrutStyle

那再回顾下前面所说的默认字体的 量度 ,这个默认字体的 量度 又是如何组成的呢?这就不得不说到  StrutStyle

如下代码所示,在之前的代码中添加 StrutStyle

  • forceStrutHeight
    forceStrutHeight
    Text
    height
    
  • 设置了 StrutStyle 的  height 设置为  1 ,这样  TextStyle 中的  height 等于  2 就没有了效果。

@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

color: Colors.purple,

alignment: Alignment.center,

child: new Row(

mainAxisAlignment: MainAxisAlignment.center,

children: <Widget>[

Container(

color: Colors.blue,

child: new Text(

"Hg",

style: TextStyle(

fontSize: 100,

height: 2,

),

strutStyle: StrutStyle(

forceStrutHeight: true,

fontSize: 100,

height: 1

),


),


),

Container(

height: 100,

width: 100,

color: Colors.red,

)

],

),

)


),

),

);

}

效果如下图所示,虽然 TextStyle 的  height 是  2 ,但是显示出现是以  StrutStyle 中  height 为   1 的效果为准。

带你深入理解 Flutter 中的字体 “冷” 知识

然后查看文档对于 StrutStyle 中  height 的描述,可以看到: height 的效果依然是  fontSize 的倍数,但是不同的是这里的对  fontSize 进行了补充说明 :  ascent + descent = fontSize ,其中:

  • ascent 代表的是基线上方部分;

  • descent 代表的是基线的下半部

  • 其组合效果如下图所示:

带你深入理解 Flutter 中的字体 “冷” 知识

Flutter 中 ascent 和   descent 是不能用代码单独设置。

除此之外, StrutStyle  的  fontSize  和  TextStyle  的  fontSize  作用并不一样 :当我们把  StrutStyle 的  fontSize 设置为  50 ,而  TextStyle 的  fontSize 依然是  100 时,如下图所示,可以看到黑色的字体大小没有发生变化,而蓝色部分的大小变为了  50 的大小。

带你深入理解 Flutter 中的字体 “冷” 知识

有人就要说那 StrutStyle 这样的  fontSize 有什么用?

这时候,如果在上面条件不变的情况下,把 Text 中的文本变成  "Hg\nHg" 这样的两行文本,可以看到换行后的文本重叠在了一起, 所以  StrutStyle 的  fontSize  也是会影响行高

带你深入理解 Flutter 中的字体 “冷” 知识

另外,在 StrutStyle 中还有另外一个参数也会影响行高,那就是  leading

如下图所示,加上了 leading 后才是 Flutter 中对字体行高完全的控制组合, leading 默认为  null ,同时它的效果也是   fontSize 的倍数,并且分布是上下均分。

带你深入理解 Flutter 中的字体 “冷” 知识

所以如下代码所示,当 StrutStyle 的  fontSize 为  100height 为 1, leading 为 1 时,可以看到  leading 的大小让蓝色区域变为了  200 ,从而 和紫色区域高度又重叠了,不同的对比之前的  Hg 在这次充满显示是居中。


@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

color: Colors.purple,

alignment: Alignment.center,

child: new Row(

mainAxisAlignment: MainAxisAlignment.center,

children: <Widget>[

Container(

color: Colors.blue,

child: new Text(

"Hg",

style: TextStyle(

fontSize: 100,

height: 2,

),

strutStyle: StrutStyle(

forceStrutHeight: true,

fontSize: 100,

height: 1,

leading: 1

),


),


),

Container(

height: 100,

width: 100,

color: Colors.red,

)

],

),

)


),

),

);

}

因为 leading 是上下均分的,而  height 是根据  ascent 和   descent 的部分放大,明显  ascent 比  ascent 大得多,所以前面的  TextStyle 的  height 为 2 时,充满后整体往下偏移。

带你深入理解 Flutter 中的字体 “冷” 知识

三、backgroundColor

那么到这里应该对于 Flutter 中关于文本大小、度量和行高等有了基本的认知,接着再介绍一个属性: TextStyle 的  backgroundColor

介绍这个属性是为了和前面的内容产生一个对比,并且解除一些误解。

如下代码所示,可以看到 StrutStyle 的  fontSize 为  100height 为  1 ,按照前面的介绍,蓝色的区域大小应该是和红色小方块一样大。

然后我们设置了 TextStyle 的  backgroundColor 为具有透明度的绿色,结果如下图所示,可以看到  backgroundColor 的区域超过了  StrutStyle ,显示为 默认情况下字体的度量


@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

color: Colors.purple,

alignment: Alignment.center,

child: new Row(

mainAxisAlignment: MainAxisAlignment.center,

children: <Widget>[

Container(

color: Colors.blue,

child: new Text(

"Hg",

style: TextStyle(

fontSize: 100,

backgroundColor: Colors.green.withAlpha(180)

),

strutStyle: StrutStyle(

forceStrutHeight: true,

fontSize: 100,

height: 1,

),


),


),

Container(

height: 100,

width: 100,

color: Colors.red,

)

],

),

)


),

),

);

}

带你深入理解 Flutter 中的字体 “冷” 知识

这是不是很有意思,事实上也可以反应出,字体的度量其实一直都是默认的 ascent + descent = fontSize ,我们可以改变  TextStyle 的  height 或者   StrutStyle 来改变行高效果,但是本质上的  fontSize 其实并没有变。

如果把输入内容换成 "H\ng" ,如下图所示可以看到更有意思的效果。

带你深入理解 Flutter 中的字体 “冷” 知识

四、TextBaseline

最后再介绍一个属性 : TextStyle 的  TextBaseline ,因为这个属性一直让人产生“误解”。

关于 TextBaseline 有两个属性,分别是  alphabetic 和  ideographic ,为了更方便解释他们的效果,如下代码所示,我们通过  CustomPaint 把不同的基线位置绘制出来。


@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Container(

height: 200,

width: 400,

color: Colors.purple,

child: CustomPaint(

painter: Text2Painter(),

),

)


),

),

);

}

class Text2Painter extends CustomPainter {

@override

void paint(Canvas canvas, Size size) {

var baseLine = TextBaseline.alphabetic;

//var baseLine = TextBaseline.ideographic;


final textStyle =

TextStyle(color: Colors.white, fontSize: 100, textBaseline: baseLine);

final textSpan = TextSpan(

text: 'My文字',

style: textStyle,

);

final textPainter = TextPainter(

text: textSpan,

textDirection: TextDirection.ltr,

);

textPainter.layout(

minWidth: 0,

maxWidth: size.width,

);


final left = 0.0;

final top = 0.0;

final right = textPainter.width;

final bottom = textPainter.height;

final rect = Rect.fromLTRB(left, top, right, bottom);

final paint = Paint()

..color = Colors.red

..style = PaintingStyle.stroke

..strokeWidth = 1;

canvas.drawRect(rect, paint);


// draw the baseline

final distanceToBaseline =

textPainter.computeDistanceToActualBaseline(baseLine);


canvas.drawLine(

Offset(0, distanceToBaseline),

Offset(textPainter.width, distanceToBaseline),

paint..color = Colors.blue..strokeWidth = 5,

);


// draw the text

final offset = Offset(0, 0);

textPainter.paint(canvas, offset);

}


@override

bool shouldRepaint(CustomPainter oldDelegate) => true;

}

如下图所示,蓝色的线就是 baseLine,从效果可以直观看到不同 baseLine 下对齐的位置应该在哪里。

带你深入理解 Flutter 中的字体 “冷” 知识

但是事实上 baseLine 的作用并不会直接影响 TextStyle 中文本的对齐方式,Flutter 中默认显示的文本只会通过  TextBaseline.alphabetic 对齐的,如下图所示官方人员也对这个问题有过描述 #47512。

带你深入理解 Flutter 中的字体 “冷” 知识

这也是为什么要用 CustomPaint 展示的原因,因为用默认  Text 展示不出来。

举个典型的例子,如下代码所示,虽然在 Row 和  Text 上都用了  ideographic ,但是其实并没有达到我们想要的效果。

@override

Widget build(BuildContext context) {

return Scaffold(

backgroundColor: Colors.black,

body: Container(

color: Colors.lime,

alignment: Alignment.center,

child: Container(

alignment: Alignment.center,

child: Row(

crossAxisAlignment: CrossAxisAlignment.baseline,

textBaseline: TextBaseline.ideographic,

mainAxisSize: MainAxisSize.max,

children: [

Text(

'我是中文',

style: TextStyle(

fontSize: 55,

textBaseline: TextBaseline.ideographic,

),

),

Spacer(),

Text('123y56',

style: TextStyle(

fontSize: 55,

textBaseline: TextBaseline.ideographic,

)),

])),

),

);

}

关键就算 Row 设置了  center ,这段文本看起来还是不是特别“对齐”。

带你深入理解 Flutter 中的字体 “冷” 知识

自从,关于 Flutter 中的字体相关的“冷”知识介绍完了,不知道你“无用”的知识有没有增多呢?

带你深入理解 Flutter 中的字体 “冷” 知识

以上所述就是小编给大家介绍的《带你深入理解 Flutter 中的字体 “冷” 知识》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Linux Programming Interface

The Linux Programming Interface

Michael Kerrisk / No Starch Press / 2010-11-6 / GBP 79.99

The Linux Programming Interface describes the Linux API (application programming interface)-the system calls, library functions, and other low-level interfaces that are used, directly or indirectly, b......一起来看看 《The Linux Programming Interface》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具