Flutter笔记:DefaultTextStyle和DefaultTextHeightBehavior解读

Flutter笔记
DefaultTextStyle和DefaultTextHeightBehavior解读

- 文章信息 - Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSitehttp://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/138244339
HuaWei:https://bbs.huaweicloud.com/blogs/426427

【介绍】:本文将详细介绍DefaultTextStyle和DefaultTextHeightBehavior这两个类的功能、原理、用法以及设计思想,并提供一些应用示例,以帮助开发者更好地理解和使用这些工具来统一和管理 Flutter 应用中的文本表现。

flutter-ljc


1. 概述

DefaultTextStyleDefaultTextHeightBehavior 是 Flutter 中用于定义和继承文本样式和文本高度行为的两个重要类。这些类允许开发者在小部件树中设置默认的文本样式和行为,这些设置会被下面的 Text 小部件继承。

本文将详细介绍这两个类的功能、原理、用法以及设计思想,并提供一些应用示例,以帮助开发者更好地理解和使用这些工具来统一和管理 Flutter 应用中的文本表现。

2. DefaultTextStyle

2.1 功能

DefaultTextStyle 是一个继承小部件,用于定义整个小部件树中 Text 小部件的默认文本样式。当 Text 小部件在其构造函数中没有指定样式时,它会从其构建上下文中查找 DefaultTextStyle 并应用找到的样式。这使得开发者可以在小部件树的任何级别上设置默认的文本样式,而所有下级 Text 小部件都会自动继承这些样式,除非它们显式定义了自己的样式。

2.2 原理

2.2.1 继承机制

DefaultTextStyle 利用 Flutter 的继承机制来传递文本样式。它是一个 InheritedWidget,这意味着它可以将数据传递给它的子树中的小部件。当 Text 小部件需要确定其样式时,它会向上遍历小部件树,寻找最近的 DefaultTextStyle 从中继承样式。要了解 DefaultTextStyle 的原理,可以从其继承关系入手,如图所示展示了该类在Flutter框架层中的继承关系:

«abstract»
Widget
Widget()
«abstract»
ProxyWidget
ProxyWidget(Widget child)
«abstract»
InheritedWidget
InheritedWidget(Widget child)
bool updateShouldNotify(InheritedWidget oldWidget)
«abstract»
InheritedTheme
InheritedTheme(Widget child)
Widget wrap(BuildContext context, Widget child)
DefaultTextStyle
DefaultTextStyle(Widget child, TextStyle style)
  • Widget: 它是一个抽象的组件基类,定义了 Flutter UI 框架的基本结构和功能。所有 Flutter 小部件的基础。

  • ProxyWidget: 代理小部件,用于包装另一个小部件。它也是是一个抽象类,允许开发者在子小部件和父小部件之间插入额外的逻辑。

  • InheritedWidget: 用于在小部件树中有效地传递数据。它是一个抽象类,允许从父小部件到子小部件的数据继承,通常用于跨多个层级的状态或配置共享。

  • InheritedTheme:专门用于主题数据的继承。
    它是一个抽象类,允许主题数据在小部件树中传递,并提供 wrap 方法来将主题数据应用到子树中。

  • DefaultTextStyle:用于定义默认的文本样式,这些样式会被小部件树中的 Text 小部件继承。它继承自 InheritedTheme,使得文本样式可以作为主题的一部分在小部件树中传递和覆盖。

从上面的继承可以看到,DefaultTextStyle 是一个 InheritedWidget,这是 Flutter 中用于在小部件树中向下传递数据的一种机制。作为 InheritedWidgetDefaultTextStyle 允许在小部件树中的任何位置定义文本样式,而这些样式将自动应用到其子树中的所有 Text 小部件上,除非这些 Text 小部件指定了自己的显式样式。

这种继承机制的工作原理是,当 Text 小部件在构建过程中需要确定其样式时,它会向上遍历小部件树,寻找最近的 DefaultTextStyle 小部件,并从中继承样式。如果在树中找不到 DefaultTextStyle,则会使用 Flutter 的默认文本样式

这种机制极大地简化了文本样式的管理,特别是在大型应用中,可以在顶层定义一个 DefaultTextStyle,这样所有的文本小部件默认都会继承这些样式,除非特别指定了其他样式。这不仅保证了样式的一致性,还减少了重复代码的需要。

2.2.2 样式合并

DefaultTextStyle 提供了一个 merge 构造函数,允许开发者基于当前环境中的 DefaultTextStyle 创建一个新的 DefaultTextStyle,同时可以覆盖某些属性。这是通过合并现有的文本样式与新提供的文本样式属性来实现的,使得开发者可以在保留大部分默认样式的基础上进行细微调整。

在实际开发中,可能需要在某个特定的屏幕或组件中稍微调整文本的样式,而不影响全局的默认样式。使用 merge 方法可以实现这一点,例如,可能需要改变特定区域的字体大小或颜色。

merge 方法首先通过 DefaultTextStyle.of(context) 获取当前 BuildContext 中的 DefaultTextStyle。然后,它创建一个新的 DefaultTextStyle 实例,其中包含从父样式继承的属性,同时将任何非空的新属性值合并进来。

这里是 merge 方法的具体实现:

static Widget merge({
  Key? key,
  TextStyle? style,
  TextAlign? textAlign,
  bool? softWrap,
  TextOverflow? overflow,
  int? maxLines,
  TextWidthBasis? textWidthBasis,
  required Widget child,
}) {
  return Builder(
    builder: (BuildContext context) {
      final DefaultTextStyle parent = DefaultTextStyle.of(context);
      return DefaultTextStyle(
        key: key,
        style: parent.style.merge(style),
        textAlign: textAlign ?? parent.textAlign,
        softWrap: softWrap ?? parent.softWrap,
        overflow: overflow ?? parent.overflow,
        maxLines: maxLines ?? parent.maxLines,
        textWidthBasis: textWidthBasis ?? parent.textWidthBasis,
        child: child,
      );
    },
  );
}

merge 方法的工作原理如下:

  1. 继承现有样式:首先,它会从当前的 BuildContext 中获取最近的 DefaultTextStyle 实例,这个实例定义了当前文本样式的默认值。

  2. 合并新样式:然后,它将这个现有的样式与通过 merge 方法传入的新样式属性进行合并。这里的合并是指,对于每个样式属性,如果在新样式中明确指定了一个值(即非null),则使用新的值;如果新样式中该属性为null,则保留现有样式中的值。

  3. 应用结果:最终,这个合并后的样式将被应用到 DefaultTextStyle 小部件的子树中,从而影响所有未显式指定自己样式的 Text 小部件。

2.3 用法解析

DefaultTextStyle 可以在任何需要统一文本样式的场景中使用,例如设置整个应用或页面的基本字体样式、颜色、字体大小等。它特别适用于那些需要确保文本样式一致性的大型应用,通过在应用的顶层设置 DefaultTextStyle,可以确保所有子页面和组件都继承相同的基本样式。

  1. 全局文本样式设置

    在 Flutter 应用的根部(通常是在 MaterialAppCupertinoAppbuilder 属性中)设置 DefaultTextStyle,可以定义全应用通用的文本样式。这样,除非在子小部件中显式指定了不同的样式,否则所有的 Text 小部件都会继承这些样式。这种方法特别适用于那些需要确保文本样式一致性的大型应用。

const MaterialApp(
  home: DefaultTextStyle(
    style: TextStyle(color: Colors.black, fontSize: 20),
    child: HomeScreen(),
  ),
);
  1. 局部样式继承和覆盖

    在应用的某个特定部分,如一个特定的屏幕或组件中,可以使用 DefaultTextStyle 来继承并修改上层定义的样式。例如,在一个特定的页面中,你可能想要改变文本的颜色或字体大小,而不影响其他页面。通过使用 DefaultTextStyle.merge,可以在保留大部分样式的基础上进行这些调整。

DefaultTextStyle.merge(
  style: TextStyle(color: Colors.blue),
  child: Text("该文本将是蓝色的,其大小继承自父文本。"),
);
  1. 动态样式调整

    在需要根据应用状态或用户交互动态改变文本样式的场景中,DefaultTextStyle 同样非常有用。例如,可以在用户选择了一个主题偏好后,更新 DefaultTextStyle 来反映这一选择,从而改变整个应用中的文本样式。

setState(() {
  currentStyle = TextStyle(color: userPreferredColor);
});

return DefaultTextStyle(
  style: currentStyle,
  child: ChildWidget(),
);

通过这些方法,DefaultTextStyle 不仅提供了一种高效的方式来管理和继承文本样式,还极大地简化了在 Flutter 应用中实现一致性和可维护性的文本样式的过程。

2.4 设计思想

在深入了解了 DefaultTextStyle 的功能和工作原理后,我们可以从 Flutter 框架的设计层面来探讨其背后的设计思想。DefaultTextStyle 的设计主要目的是为了提供一种简便的方式来统一管理和继承文本样式,这样做有几个显著的优点:

  1. 减少重复代码:通过在小部件树的适当位置设置 DefaultTextStyle,可以确保所有子部件默认继承相同的样式,除非显式指定其他样式。这减少了在每个文本小部件中重复定义样式的需要,从而简化了代码的维护。

  2. 提高样式一致性:在应用的顶层或功能模块层设置统一的文本样式,可以保证整个应用或模块中文本的显示一致性。这对于保持品牌形象和用户界面的专业性至关重要。

  3. 易于调整和扩展:随着应用的发展,可能需要对文本样式进行调整以适应新的设计需求或用户偏好。DefaultTextStyle 的继承机制使得这些调整可以快速地在全局范围内实施,而不需要逐个修改每个文本小部件。

  4. 支持动态主题切换:Flutter 应用常常需要支持动态主题切换,如夜间模式或用户自定义主题。DefaultTextStyle 使得这种切换过程更加平滑,因为只需在顶层更改文本样式,就能影响到整个应用中的所有文本显示。

通过这些设计思想的实现,DefaultTextStyle 不仅提高了开发效率,还增强了应用的可维护性和用户体验。这种设计模式体现了 Flutter 框架对于“一次定义,到处使用”的原则,使得开发者可以更加专注于内容的创造,而不是样式的反复调整。

3. DefaultTextHeightBehavior

在实际开发中,DefaultTextStyle 使用得更为频繁,因为文本样式(如字体大小、颜色、字体等)是界面设计中经常需要调整和统一的属性。DefaultTextStyle 提供了一种方便的方式来设置和继承这些样式属性,使得开发者可以轻松地管理整个应用或特定部分的文本外观。

相比之下,DefaultTextHeightBehavior 的使用场景相对较少,这是因为文本的高度行为(如行间距和对齐方式)通常不需要频繁调整。然而,DefaultTextHeightBehavior 在处理复杂文本布局时仍然非常有用,尤其是当需要精细控制文本的行高、行间距或裁剪方式时。

例如,在创建一个具有丰富文本排版需求的阅读应用或文档编辑器时,DefaultTextHeightBehavior 可以帮助开发者统一设置文本的行为,如确保所有文本行的基线对齐或调整行间距以提高可读性。此外,如果应用需要支持多种语言,其中某些语言(如阿拉伯语或泰语)可能需要特定的文本高度行为设置以正确显示,DefaultTextHeightBehavior 就显得尤为重要。

3.1 DefaultTextHeightBehavior的功能

DefaultTextHeightBehavior 是一个专门用于控制文本高度行为的 Flutter 小部件。它的主要功能是为其子树中的 TextEditableText 小部件提供一个默认的 TextHeightBehavior。这个行为决定了文本的行高如何被计算,包括行间距和文本的对齐方式。

TextEditableText 小部件在其构造函数中没有显式指定 textHeightBehavior 时,它们会从其构建上下文中查找最近的 DefaultTextHeightBehavior 并应用找到的行为。如果在小部件树中找不到 DefaultTextHeightBehavior,则这些文本小部件将使用 Flutter 的默认行高行为。

此外,如果 DefaultTextStyle 小部件(它控制文本样式)也指定了 textHeightBehavior,并且位于 DefaultTextHeightBehavior 下方,则 Text 小部件将优先使用 DefaultTextStyle 中的 textHeightBehavior 而不是 DefaultTextHeightBehavior 中的设置。这提供了一种灵活的方式来精细控制文本的显示,特别是在复杂的布局中。

3.2 原理解析

3.2.1 继承机制

DefaultTextHeightBehavior 是一个继承小部件,类似于 DefaultTextStyle,它利用 Flutter 的继承机制来传递文本高度行为设置。作为一个 InheritedWidgetDefaultTextHeightBehavior 允许开发者在小部件树的任何位置定义文本的高度行为,这些设置会自动应用到其子树中的所有 TextEditableText 小部件上,除非这些小部件显式指定了自己的 textHeightBehavior

«abstract»
Widget
Widget()
«abstract»
ProxyWidget
ProxyWidget(Widget child)
«abstract»
InheritedWidget
InheritedWidget(Widget child)
bool updateShouldNotify(InheritedWidget oldWidget)
«abstract»
InheritedTheme
InheritedTheme(Widget child)
Widget wrap(BuildContext context, Widget child)
DefaultTextHeightBehavior
DefaultTextHeightBehavior(Widget child, TextHeightBehavior textHeightBehavior)

通过这种继承机制,DefaultTextHeightBehavior 提供了一种简便的方式来统一管理和继承文本的高度行为,从而简化了在 Flutter 应用中实现一致性和可维护性的文本显示的过程。

这种继承机制的工作原理是,当 TextEditableText 小部件在构建过程中需要确定其高度行为时,它会向上遍历小部件树,寻找最近的 DefaultTextHeightBehavior 小部件,并从中继承 textHeightBehavior。如果在树中找不到 DefaultTextHeightBehavior,则这些文本小部件将使用 Flutter 的默认行高行为。

通过这种机制,DefaultTextHeightBehavior 提供了一种简便的方式来统一管理和继承文本的高度行为,从而简化了在 Flutter 应用中实现一致性和可维护性的文本显示的过程。

3.2.2 行为覆盖

在 Flutter 的布局和继承机制中,DefaultTextHeightBehaviorDefaultTextStyle 都提供了对文本行为的控制。然而,当这两者在小部件树中同时存在时,可能会出现需要确定优先级的情况。

具体来说,如果在 DefaultTextHeightBehavior 下方的小部件树中存在一个 DefaultTextStyle,并且这个 DefaultTextStyle 实例定义了一个非空的 textHeightBehavior,那么在这个范围内的 TextEditableText 小部件将优先使用 DefaultTextStyle 中定义的 textHeightBehavior,而不是从 DefaultTextHeightBehavior 中继承的行为。

这种行为覆盖机制允许更精细的控制文本显示的行为,尤其是在复杂的布局中,开发者可能需要在某些特定区域内调整文本的行高行为,而不影响全局的设置。例如,在一个具有密集文本的新闻阅读应用界面中,可能希望摘要部分的文本行高不同于正文内容,以便提高阅读的舒适度和效率。

通过这种方式,Flutter 提供了一种灵活而强大的方法来处理文本显示的细节,使得开发者可以根据具体的界面需求和设计标准,调整和优化用户的阅读体验。

3.3 用法解析

DefaultTextHeightBehavior 的使用主要集中在需要精确控制文本行高和行为的场景中。这个小部件通过提供一个统一的行为设置,使得开发者可以在整个应用或特定部分的文本显示中实现一致的行高和对齐方式。以下是一些具体的使用场景和方法:

3.3.1 全局设置

在应用的顶层设置 DefaultTextHeightBehavior 可以确保所有下层的 TextEditableText 小部件继承相同的文本高度行为。这种方法适用于需要全局统一文本行为的应用,如电子书阅读器或文档编辑器,其中文本的一致性和可读性至关重要。

DefaultTextHeightBehavior(
  // 定义文本的高度行为,不应用高度到第一个上升和最后一个下降
  textHeightBehavior: TextHeightBehavior(
    applyHeightToFirstAscent: false, // 不应用高度到第一个上升
    applyHeightToLastDescent: false  // 不应用高度到最后一个下降
  ),
  child: MaterialApp(
    home: HomeScreen(),
  ),
);

3.3.2 局部覆盖

在特定页面或组件中,可以使用 DefaultTextHeightBehavior 来覆盖上层设置的行为,或为该部分的文本提供特定的行为。这种方法适用于某些页面或组件需要与全局设置不同的文本行为的情况。

DefaultTextHeightBehavior(
  // 定义文本的高度行为
  textHeightBehavior: TextHeightBehavior(
    applyHeightToFirstAscent: true, // 将高度应用于第一个上升
    applyHeightToLastDescent: true  // 将高度应用于最后一个下降
  ),
  // 包裹一个列布局,包含子组件
  child: Column(
    children: [
      Text("该文本遵循特定的高度行为。"), // 显示一个文本部件
      // 其他部件
    ],
  ),
);

3.3.3 动态调整

在应用运行时,根据用户的选择或其他条件动态调整文本的高度行为。例如,用户可以选择不同的阅读模式,每种模式下的文本行高和对齐方式可能不同。通过在状态更改时更新 DefaultTextHeightBehavior,可以实现这种动态调整。

setState(() {
  // 从用户首选项中获取应用的文本高度行为并更新当前文本高度行为
  currentTextHeightBehavior = TextHeightBehavior(
    applyHeightToFirstAscent: userPreference.applyHeightToFirstAscent, // 应用高度到第一个上升
    applyHeightToLastDescent: userPreference.applyHeightToLastDescent  // 应用高度到最后一个下降
  );
});

return DefaultTextHeightBehavior(
  textHeightBehavior: currentTextHeightBehavior, // 设置文本的高度行为
  child: ChildWidget(), // 返回包含子部件的小部件
);

通过这些使用方法,DefaultTextHeightBehavior 提供了一种灵活而强大的方式来控制文本的高度行为,使得开发者可以根据具体的需求和设计标准,优化用户的阅读体验和界面的视觉表现。

4. 更多应用示例

4.1 统一应用主题

在 Flutter 应用开发中,确保整个应用具有统一的文本样式和文本高度行为不仅有助于保持界面的一致性,还能提升用户的使用体验。通过在应用的根部设置 DefaultTextStyleDefaultTextHeightBehavior,我们可以确保所有的页面和组件都能继承相同的文本样式和行为,从而避免在每个单独的页面或组件中重复设置样式。现在我们来看一个比较完整性的例子。

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '统一主题示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const DefaultTextStyle(
        // 设置默认的文本样式
        style: TextStyle(
          fontSize: 20,
          color: Colors.black,
          fontFamily: 'Georgia',
        ),
        // 设置默认的文本高度行为
        child: DefaultTextHeightBehavior(
          textHeightBehavior: TextHeightBehavior(
            applyHeightToFirstAscent: true,
            applyHeightToLastDescent: true,
          ),
          child: MyHomePage(title: '文本样式案例'),
        ),
      ),
    );
  }
}

可以看到,上面的代码中,MyHomePage被包裹在DefaultTextStyleDefaultTextHeightBehavior中间,分别设置了默认的文本样式和默认的文本高度行为,下面是MyHomePage类的实现。

class MyHomePage extends StatelessWidget {
  final String title;

  const MyHomePage({super.key, required this.title});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '你好,世界!',
              style: TextStyle(
                fontSize: 24, // 这里的样式会覆盖 DefaultTextStyle 中的样式
                color: Colors.red,
              ),
            ),
            Text(
              '这是一个示例文本。',
            ),
            Text(
              '这些文本将继承应用的默认样式。',
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们首先在 MyApp 类中设置了 DefaultTextStyleDefaultTextHeightBehavior。这两个设置被放置在 MaterialApphome 属性中,确保它们能够影响到整个应用中的所有页面和组件。

  • DefaultTextStyle 设置了全局的文本样式,如字体大小、颜色和字体家族。

  • DefaultTextHeightBehavior 设置了文本的高度行为,如是否应用高度到第一行的上升和最后一行的下降。

代码的运行效果如图所示。
在这里插入图片描述

任何在这之后创建的 Text 组件,如果没有指定自己的样式,都会继承这些默认设置。这样,我们就可以很容易地管理和维护整个应用的文本显示风格,确保风格的统一性。

4.2 特定页面的样式调整

在 Flutter 应用中,虽然我们可以在全局层面设置统一的文本样式,但有时候我们需要在特定页面上调整文本样式以满足特定的设计需求,而不影响全局的文本样式设置。这时,DefaultTextStyle.merge 方法就显得非常有用。

DefaultTextStyle.merge 允许我们在继承全局文本样式的基础上,对特定页面的文本样式进行调整。这种方法的优点是可以保留大部分全局样式的同时,只修改需要改变的部分。

以下是一个使用 DefaultTextStyle.merge 调整特定页面文本样式的示例:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        textTheme: const TextTheme(
          bodyMedium: TextStyle(color: Colors.black, fontSize: 16),
        ),
      ),
      home: const SpecificPage(),
    );
  }
}

class SpecificPage extends StatelessWidget {
  const SpecificPage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("特定页面"),
      ),
      body: DefaultTextStyle.merge(
        style: const TextStyle(color: Colors.red, fontSize: 24), // 覆盖全局颜色和字体大小
        child: const Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text("这是特定页面的标题,红色,24号字体"),
            Text("这段文本继承了全局样式,但字体颜色和大小被覆盖"),
            Text("继续保持特定页面的样式设置"),
          ],
        ),
      ),
    );
  }
}

在这个例子中,SpecificPage 使用 DefaultTextStyle.merge 来调整页面内所有文本的颜色和字体大小。这样做的好处是,即使全局样式发生变化,这个页面的特定样式也不会受到影响,从而确保了设计的一致性和专业性。代码运行后的效果如图所示:

在这里插入图片描述

在这个例子中,SpecificPage 使用 DefaultTextStyle.merge 来调整页面内所有文本的颜色和字体大小。这样做的好处是,即使全局样式发生变化,这个页面的特定样式也不会受到影响,从而确保了设计的一致性和专业性。

5. 结论

DefaultTextStyleDefaultTextHeightBehavior 提供了强大的工具来统一和继承文本样式和文本高度行为,使得 Flutter 应用的开发更加模块化和可管理。通过这些工具,开发者可以更容易地维护和更新应用的视觉表现,确保文本的一致性和可读性。

最后,发笔记纯当交个朋友。Flutter早年在相对冷门。近两年卖课的越来越多,目前有一些人的课可能还不如来翻一下我的笔记。

F. 附录

F.1 DefaultTextStyle类源码

/// 用于应用于没有显式样式的后代 [Text] 小部件的文本样式。
///
/// ```dart
///   /// 这个示例展示了如何使用 [DefaultTextStyle.merge] 创建一个默认文本样式,
///   /// 该样式继承当前默认文本样式的样式信息并覆盖一些属性。
///   /// 
///   /// ** 请参见示例代码 examples/api/lib/widgets/text/text.0.dart **
/// ```
///
/// 另请参阅:
///
///  * [AnimatedDefaultTextStyle],它可以在给定的持续时间内平滑地动画变化的文本样式。
///  * [DefaultTextStyleTransition],它接受一个提供的 [Animation],可以在一段时间内平滑地动画文本样式的变化。
class DefaultTextStyle extends InheritedTheme {
  /// 为给定的子树创建默认文本样式。
  ///
  /// 考虑使用 [DefaultTextStyle.merge] 来继承给定 [BuildContext] 的当前默认文本样式的样式信息。
  ///
  /// [maxLines] 属性可能为空(实际上默认为空),但如果它不为空,则必须大于零。
  const DefaultTextStyle({
    super.key,
    required this.style,
    this.textAlign,
    this.softWrap = true,
    this.overflow = TextOverflow.clip,
    this.maxLines,
    this.textWidthBasis = TextWidthBasis.parent,
    this.textHeightBehavior,
    required super.child,
  }) : assert(maxLines == null || maxLines > 0);

  /// 提供回退值的可常量构造的默认文本样式。
  ///
  /// 当给定的 [BuildContext] 没有封闭的默认文本样式时,从 [of] 返回。
  ///
  /// 此构造函数创建一个带有无效 [child] 的 [DefaultTextStyle],这意味着构造的值不能合并到树中。
  const DefaultTextStyle.fallback({ super.key })
    : style = const TextStyle(),
      textAlign = null,
      softWrap = true,
      maxLines = null,
      overflow = TextOverflow.clip,
      textWidthBasis = TextWidthBasis.parent,
      textHeightBehavior = null,
      super(child: const _NullWidget());

  /// 创建一个默认文本样式,覆盖小部件树中此处的文本样式。
  ///
  /// 给定的[style]与插入小部件的[BuildContext]中的默认文本样式合并,
  /// 并且任何其他参数(不为null)都将替换该默认文本样式上的相应属性。
  ///
  /// 此构造函数不能用于覆盖祖先的[maxLines]属性,该属性的值为null,因为此处的null表示“推迟到祖先”。
  /// 若要将祖先的非null[maxLines]替换为null值(以移除对行数的限制),请手动使用[DefaultTextStyle.of]获取环境[DefaultTextStyle],
  /// 然后直接使用[DefaultTextStyle.new]构造函数创建一个新的[DefaultTextStyle]。
  /// 请参阅下面的源代码示例,了解如何执行此操作(因为这基本上就是此构造函数的作用)。
  static Widget merge({
    Key? key,
    TextStyle? style,
    TextAlign? textAlign,
    bool? softWrap,
    TextOverflow? overflow,
    int? maxLines,
    TextWidthBasis? textWidthBasis,
    required Widget child,
  }) {
    return Builder(
      builder: (BuildContext context) {
        final DefaultTextStyle parent = DefaultTextStyle.of(context);
        return DefaultTextStyle(
          key: key,
          style: parent.style.merge(style),
          textAlign: textAlign ?? parent.textAlign,
          softWrap: softWrap ?? parent.softWrap,
          overflow: overflow ?? parent.overflow,
          maxLines: maxLines ?? parent.maxLines,
          textWidthBasis: textWidthBasis ?? parent.textWidthBasis,
          child: child,
        );
      },
    );
  }
  /// 要应用的文本样式。
  final TextStyle style; 

  /// 文本小部件中每行文本应如何在水平方向上对齐。
  final TextAlign? textAlign; 

  /// 文本是否应在软换行处中断。
  ///
  /// 如果为false,则文本中的字形将被定位,就好像有无限的水平空间一样。
  ///
  /// 这也决定了[overflow]属性的行为。如果这是true或null,
  /// 导致溢出的字形以及随后的字形将不会被呈现。
  final bool softWrap; 

  /// 应如何处理视觉溢出。
  ///
  /// 如果[softWrap]为true或null,则导致溢出的字形以及随后的字形将不会被呈现。
  /// 否则,将以给定的溢出选项显示。
  final TextOverflow overflow; 

  /// 文本跨度的可选最大行数,必要时进行换行。
  /// 如果文本超出给定行数,将根据[overflow]进行截断。
  ///
  /// 如果为1,则文本不会换行。否则,文本将在框的边缘处换行。
  ///
  /// 如果这是非null的,则即使是[Text.maxLines]的显式null值也会被覆盖。
  final int? maxLines;

  /// 计算文本宽度时要使用的策略。
  ///
  /// 可能的值及其含义,请参阅[TextWidthBasis]。
  final TextWidthBasis textWidthBasis;

  /// {@macro dart.ui.textHeightBehavior}
  final ui.TextHeightBehavior? textHeightBehavior;

  /// 包围给定上下文的最近的此类实例。
  ///
  /// 如果不存在这样的实例,则返回由[DefaultTextStyle.fallback]创建的实例,其中包含回退值。
  ///
  /// 典型用法如下:
  ///
  /// ```dart
  /// DefaultTextStyle style = DefaultTextStyle.of(context);
  /// ```
  static DefaultTextStyle of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<DefaultTextStyle>() ?? const DefaultTextStyle.fallback();
  }

  
  bool updateShouldNotify(DefaultTextStyle oldWidget) {
    return style != oldWidget.style ||
        textAlign != oldWidget.textAlign ||
        softWrap != oldWidget.softWrap ||
        overflow != oldWidget.overflow ||
        maxLines != oldWidget.maxLines ||
        textWidthBasis != oldWidget.textWidthBasis ||
        textHeightBehavior != oldWidget.textHeightBehavior;
  }

  
  Widget wrap(BuildContext context, Widget child) {
    return DefaultTextStyle(
      style: style,
      textAlign: textAlign,
      softWrap: softWrap,
      overflow: overflow,
      maxLines: maxLines,
      textWidthBasis: textWidthBasis,
      textHeightBehavior: textHeightBehavior,
      child: child,
    );
  }

  
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    style.debugFillProperties(properties);
    properties.add(EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null));
    properties.add(FlagProperty('softWrap', value: softWrap, ifTrue: 'wrapping at box width', ifFalse: 'no wrapping except at line break characters', showName: true));
    properties.add(EnumProperty<TextOverflow>('overflow', overflow, defaultValue: null));
    properties.add(IntProperty('maxLines', maxLines, defaultValue: null));
    properties.add(EnumProperty<TextWidthBasis>('textWidthBasis', textWidthBasis, defaultValue: TextWidthBasis.parent));
    properties.add(DiagnosticsProperty<ui.TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
  }
}

F.1 DefaultTextHeightBehavior类源码

/// 将应用于未明确设置 [Text.textHeightBehavior] 的后代 [Text] 和 [EditableText] 小部件的 [TextHeightBehavior]。
///
/// 如果此小部件下方存在具有非空 [DefaultTextStyle.textHeightBehavior] 的 [DefaultTextStyle],
/// 则将使用 [DefaultTextStyle.textHeightBehavior] 而不是此小部件的 [TextHeightBehavior]。
///
/// 另请参阅:
///
///  * [DefaultTextStyle],它定义了要应用于后代 [Text] 小部件的 [TextStyle]。
class DefaultTextHeightBehavior extends InheritedTheme {
  /// 为给定的子树创建默认文本高度行为。
  const DefaultTextHeightBehavior({
    super.key,
    required this.textHeightBehavior,
    required super.child,
  });

  /// {@macro dart.ui.textHeightBehavior}
  final TextHeightBehavior textHeightBehavior;

  /// 包围给定上下文的最接近的 [DefaultTextHeightBehavior] 实例,如果找不到则为 null。
  ///
  /// 如果不存在这样的实例,则此方法将返回 `null`。
  ///
  /// 调用此方法将在 [context] 中创建对最近的 [DefaultTextHeightBehavior] 的依赖,如果存在。
  ///
  /// 典型用法如下:
  ///
  /// ```dart
  /// TextHeightBehavior? defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
  /// ```
  ///
  /// See also:
  ///
  /// * [DefaultTextHeightBehavior.maybeOf], which is similar to this method,
  ///   but asserts if no [DefaultTextHeightBehavior] ancestor is found.
  static TextHeightBehavior? maybeOf(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<DefaultTextHeightBehavior>()?.textHeightBehavior;
  }
  /// 包围给定上下文的最接近的 [DefaultTextHeightBehavior] 实例。
  ///
  /// 如果不存在这样的实例,则此方法在调试模式下会断言,并在发布模式下抛出异常。
  ///
  /// 典型用法如下:
  ///
  /// ```dart
  /// TextHeightBehavior defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
  /// ```
  ///
  /// 调用此方法将在 [context] 中创建对最近的 [DefaultTextHeightBehavior] 的依赖。
  ///
  /// 另请参阅:
  ///
  /// * [DefaultTextHeightBehavior.maybeOf],类似于此方法,但如果找不到 [DefaultTextHeightBehavior] 祖先,则返回 null。
  static TextHeightBehavior of(BuildContext context) {
    final TextHeightBehavior? behavior = maybeOf(context);
    assert(() {
      if (behavior == null) {
        throw FlutterError(
          'DefaultTextHeightBehavior.of() was called with a context that does not contain a '
          'DefaultTextHeightBehavior widget.\n'
          'No DefaultTextHeightBehavior widget ancestor could be found starting from the '
          'context that was passed to DefaultTextHeightBehavior.of(). This can happen '
          'because you are using a widget that looks for a DefaultTextHeightBehavior '
          'ancestor, but no such ancestor exists.\n'
          'The context used was:\n'
          '  $context',
        );
      }
      return true;
    }());
    return behavior!;
  }

  
  bool updateShouldNotify(DefaultTextHeightBehavior oldWidget) {
    return textHeightBehavior != oldWidget.textHeightBehavior;
  }

  
  Widget wrap(BuildContext context, Widget child) {
    return DefaultTextHeightBehavior(
      textHeightBehavior: textHeightBehavior,
      child: child,
    );
  }

  
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<ui.TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/580241.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PriorityQueue—优先级队列FollowUp

FollowUp大纲&#xff1a; 思维导图&#xff1a; FollowUp PriorityQueue: Q1&#xff1a;但不知道是大根堆化石小根堆 A&#xff1a;Q1 只需要放进去几个元素peek&#xff08;&#xff09;出元素是大的还是小的 下面如果是5就是小根堆10就是大根堆 A&#xff1a;默认是小根…

Github创建远程仓库(项目)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

OPPO Reno10Pro/Reno11/K10手机强解BL刷root权限KSU内核抓包刷机救砖

OPPO Reno10Pro/Reno11/K10手机虽然发布时间并不久&#xff0c;但由于天玑处理器的体质&#xff0c;已经支持强制解锁BL了&#xff0c;该漏洞来自第三方工具适配&#xff0c;支持OPPO天机8100/8200刷机救砖解锁BL不需要等待官方深度测试直接实现。解锁BL后的OPPO Reno10Pro/Ren…

华为ensp中BGP(边界网关协议)基础原理及配置命令

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月27日10点04分 BGP&#xff08;边界网关协议&#xff09;是一种路由协议&#xff0c;用于在互联网中的不同自治系统&#xff08;AS&#xff09;之间交换路由信息。它…

Edge浏览器新特性深度解析,写作ai免费软件

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

运算符重载(2)

1.赋值运算符重载 #include<iostream> using namespace std;class Person { friend void test01(); public:Person(int age){m_Age new int(age);}/*堆区的数据由程序员手动开辟并手动释放*/~Person(){if (m_Age ! NULL){delete m_Age;}}Person& operator(Person &a…

如此建立网络根文件系统 Mount NFS RootFS

安静NFS系统服务 sudo apt-get install nfs-kernel-server 创建目录 sudo mkdir /rootfsLee 将buildroot编译的根文件系统解压缩到 sudo tar xvf rootfs.tar -C /rootfsLee/ 添加文件NFS访问路径 sudo vi /etc/exports sudo /etc/exports文件&#xff0c;添加如下一行 …

比 PSD.js 更强的下一代 PSD 解析器,支持 WebAssembly

比 PSD.js 更强的下一代 PSD 解析器&#xff0c;支持 WebAssembly 1.什么是 webtoon/ps webtoon/ps 是 Typescript 中轻量级 Adobe Photoshop .psd/.psb 文件解析器&#xff0c;对 Web 浏览器和 NodeJS 环境提供支持&#xff0c;且做到零依赖。 Fast zero-dependency PSD par…

创建SpringBoot和RabbitMQ的整合项目

文章目录 创建SpringBoot和RabbitMQ的整合项目首先快速创建一个maven项目引入SpringBoot整合rabbitMQ的依赖在src/main目录下创建resources目录并引入配置文件写消息发送者MessageSender写消息接收者MessageReceiver写RabbitMQConfig配置类写SpringBoot启动主类CommandLineRunn…

决策树模型示例

通过5个条件判定一件事情是否会发生&#xff0c;5个条件对这件事情是否发生的影响力不同&#xff0c;计算每个条件对这件事情发生的影响力多大&#xff0c;写一个决策树模型pytorch程序,最后打印5个条件分别的影响力。 一 决策树模型是一种非参数监督学习方法&#xff0c;主要…

Java高阶私房菜:JVM垃圾回收机制及算法原理探究

目录 垃圾回收机制 什么是垃圾回收机制 JVM的自动垃圾回收机制 垃圾回收机制的关键知识点 初步了解判断方法-引用计数法 GCRoot和可达性分析算法 什么是可达性分析算法 什么是GC Root 对象回收的关键知识点 标记对象可回收就一定会被回收吗&#xff1f; 可达性分析算…

使用R语言进行简单的因子分析

在本文中&#xff0c;将介绍如何使用R语言进行因子分析&#xff0c;并通过一个示例演示整个过程。因子分析是一种多元统计分析方法&#xff0c;用于探索变量之间的潜在结构和关系。R语言提供了丰富的统计工具和包&#xff0c;使因子分析的实现变得简单而高效。 准备工作 首先…

c++中的链表list的模拟实现

拖更了半个月&#xff0c;我终于来填c的坑啦。上次我们说的vetcor不知道小伙伴还记得多少呢&#xff1f;今天我们要讲list的模拟实现。 目录 架构结点list表的结构 构造函数尾插push_back()尾删pop_back()计算个数&#xff1a;size()判断空empty()※迭代器问题普通迭代器迭代器…

数据结构:实验六:图的操作

一、 实验目的 &#xff08;1&#xff09;掌握图的邻接矩阵和邻接表存储结构。 &#xff08;2&#xff09;熟练图的邻接表的基本运算。 &#xff08;3&#xff09;加深图的深度优先遍历算法和广度优先遍历算法的理解 二、 实验要求 有下图所示的带权有向图及其对应的邻…

【Python时序预测系列】麻雀算法(SSA)优化LSTM实现单变量时间序列预测(源码)

这是我的第269篇原创文章。 一、引言 麻雀算法&#xff08;Sparrow Search Algorithm&#xff0c;SSA&#xff09;是一种基于麻雀群体行为的算法&#xff0c;它可以用来优化深度学习模型中的参数。在优化LSTM模型时&#xff0c;可以通过麻雀算法来调整LSTM的参数&#xff0c;以…

亚马逊测评的目的是什么?

测评的目的&#xff1a;店铺销量、留评 特别是新品&#xff0c;一个产品销量很低也没什么评价的产品&#xff0c;很难说服真实买家们&#xff0c;因为同类目还有其他的选择&#xff0c;不管是谁都不愿意当小白鼠的&#xff0c;而且打造爆款&#xff0c;提升产品权重这些都离不…

【华为】SVI接口实验配置

【华为】SVI接口实验配置 拓扑实验要求设备核心交换机PCPC1PC2 查看VLAN验证 配置文档 拓扑 实验要求 一台三层交换机&#xff0c;两台PC PC1 和 PC2 静态获取地址&#xff0c;并处于不同VLAN 然后PC的网关是处在三层交换机LSW1身上&#xff0c;不同VLAN就是处在不同网段&…

Jenkins - macOS 上安装

文章目录 关于 JenkinsmacOS 上安装 Jenkins方式一&#xff1a;brew方式二&#xff1a;tomcat Jenkins war 关于 Jenkins 官网上下载Jenkins并将其安装到持续集成服务器 https://jenkins.io/download/ macOS 上安装 Jenkins 现在本 macOS 上测试 https://www.jenkins.io/do…

HarmonyOS 应用开发——入门

首先当然是华为的官方文档了&#xff0c;要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看&#xff0c;可以看我下面总结的干货&#xff0c;哈哈 第一个问题&#xff1a;stage架构和fa架构的区…

MySql 导出导入(备份还原)

1&#xff0c;导出备份 要导出MySQL数据库中的数据&#xff0c;使用mysqldump命令。假设要导出名为mydatabase的数据库到名为backup.sql的文件中&#xff1a; mysqldump -u 用户名 -p 数据库名 > backup.sql 参数说明&#xff1a; -u mysql用户名称 -p 执行后会要求输入…