带你深入理解 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 中的字体 “冷” 知识》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

无界面交互

无界面交互

[美]Golden Krishna / 杨名 / 人民邮电出版社 / 2017-1 / 49.00元

“真希望在硅谷工作的人们已经读过这本书了。”——Doug LeMoine,Cooper总经理 “这本书的写作看似随意,字里行间却透着一种辛辣、幽默的反叛精神,这种精神可以帮助我们走出当今交互设计的界面泥潭。当你心情低落时,不妨翻开这本书,读上几页,你会开始微笑,大笑,并从中学到很多东西。书中的文字有一股振奋人心的力量。”——Don Norman,加州大学圣迭戈分校设计实验室主任,《设计心理学......一起来看看 《无界面交互》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

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

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具