【布局 widget】Flutter Baseline

简介: 【布局 widget】Flutter Baseline

image.png

Baseline 是布局 widget,作用是让 child 的基线和指定的位置重合。Baseline 的布局逻辑不难,很多同学不知道如何用这个 widget 是因为对基线不是很理解。下面我们先看一下基线。

image.png

基线(英语:Baseline)指的是多数拉丁字母排列的基准线。如上图所示,大多字母都沿着红色基线排列。

baseline 理解了,但是 Baseline widget 还有一个参数 baselineType,这个参数是一枚举类型。

/// A horizontal line used for aligning text.
enum TextBaseline {
  /// The horizontal line used to align the bottom of glyphs for alphabetic characters.
  alphabetic,
  /// The horizontal line used to align ideographic characters.
  ideographic,
}
复制代码

把注释翻译一下

// 一条用于对齐文本的水平线
enum TextBaseline {
  /// 用于对齐字母字符字形底部的水平线
  alphabetic,
  /// 用于对齐表意字符的水平线
  ideographic,
}
复制代码

在英语中把中文,韩文等东亚文字称为 ideographic(表意)文字。比如 Fluter Widget 天天更新 这几个字放在一起的时候,基线就可以有两个 ,一个是 Fluter Widget 的基线,一个是 天天更新 的基线。

这样说了半天,可能还是不能理解,下面我们自己把这两条基线划出来。上面的是字母基线,下面的是表意基线


image.png

class myPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final textStyle = TextStyle(
      color: Colors.black,
      fontSize: 30,
    );
    final textSpan = TextSpan(
      text: 'Flutter widget每日更新IAM17',
      style: textStyle,
    );
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    );
    textPainter.layout(
      minWidth: 0,
      maxWidth: size.width,
    );
    final paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1;
    // 把 TextBaseline.ideographic 改为 TextBaseline.alphabetic 画字母基线。
    final distanceToBaseline =
        textPainter.computeDistanceToActualBaseline(TextBaseline.ideographic);
    canvas.drawLine(
      Offset(0, distanceToBaseline),
      Offset(textPainter.width, distanceToBaseline),
      paint,
    );
    final offset = Offset(0, 0);
    textPainter.paint(canvas, offset);
  }
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}
复制代码

关于基线的知识了解了,Baseline 就变得非常简单了。

布局逻辑的代码

void performLayout() {
    if (child != null) {
      final BoxConstraints constraints = this.constraints;
      child!.layout(constraints.loosen(), parentUsesSize: true);
      final double childBaseline = child!.getDistanceToBaseline(baselineType)!;
      final double actualBaseline = baseline;
      final double top = actualBaseline - childBaseline;
      final BoxParentData childParentData = child!.parentData! as BoxParentData;
      childParentData.offset = Offset(0.0, top);
      final Size childSize = child!.size;
      size =
          constraints.constrain(Size(childSize.width, top + childSize.height));
    } else {
      size = constraints.smallest;
    }
  }
复制代码

Baseline 就是让它指定的基线位置和 child 的基线重合。 我们通过示例看下。

Center(child:Container(
   decoration: BoxDecoration(border: Border.all(color: Colors.red)),
   child: Baseline(
       baseline: 100,
       baselineType: TextBaseline.ideographic,
       child: Container(
         width: 100,
         height: 100,
         color: Colors.blue[200],
))));
复制代码

我们给 Baseline 套上一个红框,用来显示它的大小。

  1. baseline 与 child baseline 值相同


image.png

在本例中 child baseline 为 100,与指定的baseline 相同,结果是 size 与 child size 相同。Baseline紧紧包裹住 child。

非文字的基线位置是 box 的底部

  1. baseline 小于 child baseline

baseline: 100  修改为   baseline: 0


image.png


size 为0。chld 在 baseline 正上方。 3. baseline 大于 child baseline

baseline: 100 修改为 baseline: 150

image.png


size 为 150,Baseline 完全包裹 child。child 在 Baseline 底部

  1. baseline 可以为负值

baseline: 100 修改为 baseline: -10


image.png

size 为 0 child 在 Baseline 上方,和 Baseline 间隔 baseline 距离。

通过这样几个示例,我们对 Baseline 的作用已经有了感观上的认识。下面思考一下它的应用场景。

Baseline 的应用场景

通过上面的例子我们可以看出 Baseline 可以做溢出效果,但如果是溢出,最好还是用 OverflowBox。Baseline 的应用应该是在文字对齐方面。比如要实现下面的效果,"IAM17” 这几个字要求紧贴红框下边。


image.png

Container(
    height: 50,
    decoration: BoxDecoration(border: Border.all(color: Colors.red)),
    child: Baseline(
      baseline: 50,
      baselineType: TextBaseline.ideographic,
      child: Text('IAM17', style: TextStyle(fontSize: 24,)),
    ),
  )
复制代码

你可能会说,如果不贴底,可以设置一个偏移,但这个偏移是多少呢?随着字体,字号的变化,这个偏移量也是变化的。

用 Baseline 可以轻松实现基线对齐,遇到基线对齐的问题,应该第一时间想到 Baseline。

目录
相关文章
|
27天前
|
缓存 监控 前端开发
优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面
本文探讨了优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面,并通过案例分析展示了具体措施和效果,强调了持续优化的重要性及未来优化方向。
54 10
|
2天前
|
存储 容器
Flutter 构建自适应布局
Flutter 构建自适应布局
Flutter 构建自适应布局
|
2天前
|
容器
Flutter Widget 解析
Flutter Widget 解析
|
26天前
|
开发框架 数据安全/隐私保护 开发者
Flutter 是一款强大的跨平台移动应用开发框架,本文深入探讨了其布局与样式设计
Flutter 是一款强大的跨平台移动应用开发框架,本文深入探讨了其布局与样式设计,涵盖布局基础、常用组件、样式设计、实战应用、响应式布局及性能优化等方面,助力开发者打造精美用户界面。
41 7
|
2天前
|
存储 容器
Flutter 有状态Widget 和 无状态Widget
Flutter 有状态Widget 和 无状态Widget
|
1月前
深入理解Flutter鸿蒙next版本 中的Widget继承:使用extends获取数据与父类约束
本文详细介绍了Flutter中如何通过继承其他Widget来创建自定义组件。首先解释了Widget继承的基本概念,包括StatelessWidget和StatefulWidget的区别。接着通过具体示例展示了如何继承StatelessWidget和StatefulWidget,并在子类中访问父类的build方法和状态。最后,结合多个自定义Widget展示了如何在实际应用中灵活使用继承和组合来构建复杂的UI。
76 8
|
1月前
|
开发者 容器
Flutter&鸿蒙next 布局架构原理详解
本文详细介绍了 Flutter 中的主要布局方式,包括 Row、Column、Stack、Container、ListView 和 GridView 等布局组件的架构原理及使用场景。通过了解这些布局 Widget 的基本概念、关键属性和布局原理,开发者可以更高效地构建复杂的用户界面。此外,文章还提供了布局优化技巧,帮助提升应用性能。
103 4
|
1月前
|
容器
flutter&鸿蒙next 使用 InheritedWidget 实现跨 Widget 传递状态
在 Flutter 中,状态管理至关重要。本文详细介绍了如何使用 InheritedWidget 实现跨 Widget 的状态传递。InheritedWidget 允许数据在 Widget 树中向下传递,适用于多层嵌套的场景。通过一个简单的计数器示例,展示了如何创建和使用 InheritedWidget,包括其基础概念、工作原理及代码实现。虽然 InheritedWidget 较底层,但它是许多高级状态管理解决方案的基础。
103 2
|
1月前
|
容器
深入理解 Flutter 鸿蒙版的 Stack 布局:适配屏幕与层叠样式布局
Flutter 的 Stack 布局组件允许你将多个子组件层叠在一起,实现复杂的界面效果。本文介绍了 Stack 的基本用法、核心概念(如子组件层叠、Positioned 组件和对齐属性),以及如何使用 MediaQuery 和 LayoutBuilder 实现响应式设计。通过示例展示了照片展示与文字描述、动态调整层叠布局等高级用法,帮助你构建更加精美和实用的 Flutter 应用。
137 2
|
2月前
|
容器
Flutter&鸿蒙next 布局架构原理详解
Flutter&鸿蒙next 布局架构原理详解