【布局 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。

目录
相关文章
|
17天前
深入理解Flutter鸿蒙next版本 中的Widget继承:使用extends获取数据与父类约束
本文详细介绍了Flutter中如何通过继承其他Widget来创建自定义组件。首先解释了Widget继承的基本概念,包括StatelessWidget和StatefulWidget的区别。接着通过具体示例展示了如何继承StatelessWidget和StatefulWidget,并在子类中访问父类的build方法和状态。最后,结合多个自定义Widget展示了如何在实际应用中灵活使用继承和组合来构建复杂的UI。
68 8
|
17天前
|
开发者 容器
Flutter&鸿蒙next 布局架构原理详解
本文详细介绍了 Flutter 中的主要布局方式,包括 Row、Column、Stack、Container、ListView 和 GridView 等布局组件的架构原理及使用场景。通过了解这些布局 Widget 的基本概念、关键属性和布局原理,开发者可以更高效地构建复杂的用户界面。此外,文章还提供了布局优化技巧,帮助提升应用性能。
78 4
|
15天前
|
容器
flutter&鸿蒙next 使用 InheritedWidget 实现跨 Widget 传递状态
在 Flutter 中,状态管理至关重要。本文详细介绍了如何使用 InheritedWidget 实现跨 Widget 的状态传递。InheritedWidget 允许数据在 Widget 树中向下传递,适用于多层嵌套的场景。通过一个简单的计数器示例,展示了如何创建和使用 InheritedWidget,包括其基础概念、工作原理及代码实现。虽然 InheritedWidget 较底层,但它是许多高级状态管理解决方案的基础。
91 2
|
17天前
|
容器
深入理解 Flutter 鸿蒙版的 Stack 布局:适配屏幕与层叠样式布局
Flutter 的 Stack 布局组件允许你将多个子组件层叠在一起,实现复杂的界面效果。本文介绍了 Stack 的基本用法、核心概念(如子组件层叠、Positioned 组件和对齐属性),以及如何使用 MediaQuery 和 LayoutBuilder 实现响应式设计。通过示例展示了照片展示与文字描述、动态调整层叠布局等高级用法,帮助你构建更加精美和实用的 Flutter 应用。
106 2
|
29天前
|
容器
Flutter&鸿蒙next 布局架构原理详解
Flutter&鸿蒙next 布局架构原理详解
|
1月前
|
Android开发 开发者 容器
flutter:&UI布局 (六)
本文档介绍了Flutter中的UI布局方式,包括线性布局(如Column和Row)、非线性布局(如Stack、Flex、Positioned)以及Wrap布局等。通过具体示例代码展示了如何使用这些布局组件来构建灵活多变的用户界面,例如使用Column垂直排列文本、使用Stack叠加组件、以及利用Wrap实现自动换行的按钮布局等。
|
1月前
|
容器
flutter:第一个flutter&Widget的使用 (二)
本文介绍了Flutter框架下的基本组件及其用法,包括简单的 Stateless Widget 如文本和按钮,以及更复杂的 StatefulWidget 示例。详细解释了如何使用 `context` 获取祖先小部件的信息,并展示了 `MaterialApp` 的属性及用途。此外,还探讨了 `StatefulWidget` 与 `StatelessWidget` 的区别,以及 `AppBar` 的常见属性配置方法。适合Flutter初学者参考学习。
|
15天前
|
Dart JavaScript 前端开发
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
Flutter 是 Google 开发的开源 UI 框架,用于快速构建高性能的移动、Web 和桌面应用。Flutter 通过 Widget 构建 UI,每个 UI 元素都是 Widget,包括文本、按钮、图片等。Widget 不仅描述外观,还描述行为,是不可变的。常见的 Widget 包括结构型(Container、Column、Row)、呈现型(Text、Image)、交互型(ElevatedButton)和状态管理型(StatefulWidget)。Flutter 与鸿蒙 Next 在组件化架构、开发语言、布局系统、性能和跨平台支持方面各有优势
67 0
|
4月前
|
容器
flutter 布局管理【详解】
flutter 布局管理【详解】
39 3
|
4月前
Flutter-自定义折叠流布局实现
Flutter-自定义折叠流布局实现
82 0