2024-03-07 flutter StrutStyle和TextStyle

StrutStyle和TextStyle区别

WX20240307-121045@2x.png

1,style和strutStyle

StrutStyle({
    String? fontFamily,
    List<String>? fontFamilyFallback,
    this.fontSize,
    this.height,
    this.leadingDistribution,
    this.leading,
    this.fontWeight,
    this.fontStyle, ///fontStyle
    this.forceStrutHeight,
    this.debugLabel,
    String? package,
  }) 




TextStyle({
    this.inherit = true,
    this.color,
    this.backgroundColor,
    this.fontSize,
    this.fontWeight,
    this.fontStyle, ///fontStyle
    this.letterSpacing,
    this.wordSpacing,
    this.textBaseline,
    this.height,
    this.leadingDistribution,
    this.locale,
    this.foreground,
    this.background,
    this.shadows,
    this.fontFeatures,
    this.fontVariations,
    this.decoration,
    this.decorationColor,
    this.decorationStyle,
    this.decorationThickness,
    this.debugLabel,
    String? fontFamily,
    List<String>? fontFamilyFallback,
    String? package,
    this.overflow,
  })

都有fontSize,height,fontWeight,fontStyle,fontFamily,fontFamilyFallback属性

flutter 源码:

   final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
    TextStyle? effectiveTextStyle = style;
    if (style == null || style!.inherit) {
      effectiveTextStyle = defaultTextStyle.style.merge(style);
    }
    if (MediaQuery.boldTextOverride(context)) {
      effectiveTextStyle = effectiveTextStyle!.merge(const TextStyle(fontWeight: FontWeight.bold));
    }

 RichText(
 
      strutStyle: strutStyle,
 
      text: TextSpan(
        style: effectiveTextStyle, //style传递给 style: TextSpan text属性了
        text: data,
        children: textSpan != null ? <InlineSpan>[textSpan!] : null,
      ),
    );



  @override
  RenderParagraph createRenderObject(BuildContext context) {
    assert(textDirection != null || debugCheckHasDirectionality(context));
    return RenderParagraph(text, ///text: style传递给 style: TextSpan text属性了
      textAlign: textAlign,
      textDirection: textDirection ?? Directionality.of(context),
      softWrap: softWrap,
      overflow: overflow,
      textScaleFactor: textScaleFactor,
      maxLines: maxLines,
      strutStyle: strutStyle, //  strutStyle
      textWidthBasis: textWidthBasis,
      textHeightBehavior: textHeightBehavior,
      locale: locale ?? Localizations.maybeLocaleOf(context),
      registrar: selectionRegistrar,
      selectionColor: selectionColor,
    );
  }




 RenderParagraph(InlineSpan text, { ///text: style传递给 style: TextSpan text属性了
    TextAlign textAlign = TextAlign.start,
    required TextDirection textDirection,
    bool softWrap = true,
    TextOverflow overflow = TextOverflow.clip,
    double textScaleFactor = 1.0,
    int? maxLines,
    Locale? locale,
    StrutStyle? strutStyle,
    TextWidthBasis textWidthBasis = TextWidthBasis.parent,
    ui.TextHeightBehavior? textHeightBehavior,
    List<RenderBox>? children,
    Color? selectionColor,
    SelectionRegistrar? registrar,
  }) :  
       _softWrap = softWrap,
       _overflow = overflow,
       _selectionColor = selectionColor,
       _textPainter = TextPainter(
         text: text, /////text: style传递给 style: TextSpan text属性了
         textAlign: textAlign,
         textDirection: textDirection,
         textScaleFactor: textScaleFactor,
         maxLines: maxLines,
         ellipsis: overflow == TextOverflow.ellipsis ? _kEllipsis : null,
         locale: locale,
         strutStyle: strutStyle, //  strutStyle
         textWidthBasis: textWidthBasis,
         textHeightBehavior: textHeightBehavior,
       ) {
    addAll(children);
    _extractPlaceholderSpans(text);
    this.registrar = registrar;
  }



  TextPainter({
    InlineSpan? text, ///////text: style传递给 style: TextSpan text属性了
    TextAlign textAlign = TextAlign.start,
    TextDirection? textDirection,
    double textScaleFactor = 1.0,
    int? maxLines,
    String? ellipsis,
    Locale? locale,
    StrutStyle? strutStyle,// //  strutStyle
    TextWidthBasis textWidthBasis = TextWidthBasis.parent,
    ui.TextHeightBehavior? textHeightBehavior,
  }) : assert(text == null || text.debugAssertIsValid()),
       assert(textAlign != null),
       assert(textScaleFactor != null),
       assert(maxLines == null || maxLines > 0),
       assert(textWidthBasis != null),
       _text = text, ///////text: style传递给 style: TextSpan text属性了
       _textAlign = textAlign,
       _textDirection = textDirection,
       _textScaleFactor = textScaleFactor,
       _maxLines = maxLines,
       _ellipsis = ellipsis,
       _locale = locale,
       _strutStyle = strutStyle,//  strutStyle
       _textWidthBasis = textWidthBasis,
       _textHeightBehavior = textHeightBehavior;



  void _createParagraph() {
    assert(_paragraph == null || _rebuildParagraphForPaint);
    final InlineSpan? text = this.text;////text: style传递给 style: TextSpan text属性了
    if (text == null) {
      throw StateError('TextPainter.text must be set to a non-null value before using the TextPainter.');
    }
    final ui.ParagraphBuilder builder = ui.ParagraphBuilder(_createParagraphStyle());/////  strutStyle


    /// //text: style传递给 style: TextSpan text属性了,
    //builder: strutStyle
    text.build(builder, textScaleFactor: textScaleFactor, dimensions: _placeholderDimensions);



    _inlinePlaceholderScales = builder.placeholderScales;
    assert(() {
      _debugMarkNeedsLayoutCallStack = null;
      return true;
    }());



    _paragraph = builder.build();



    _rebuildParagraphForPaint = false;
  }



 ParagraphBuilder(ParagraphStyle style)
    : _defaultLeadingDistribution = style._leadingDistribution {
      List<String>? strutFontFamilies;
      final StrutStyle? strutStyle = style._strutStyle;
      final ByteData? encodedStrutStyle;
      if (strutStyle != null && strutStyle._enabled) {//style._strutStyle;
        final String? fontFamily = strutStyle._fontFamily;
        strutFontFamilies = <String>[
          if (fontFamily != null) fontFamily,
          ...?strutStyle._fontFamilyFallback,
        ];

        assert(TextLeadingDistribution.values.length <= 2);
        final TextLeadingDistribution leadingDistribution = strutStyle._leadingDistribution
          ?? style._leadingDistribution;
        encodedStrutStyle = strutStyle._encoded;
        int bitmask = encodedStrutStyle.getInt8(0);
        bitmask |= (leadingDistribution.index) << 3;
        encodedStrutStyle.setInt8(0, bitmask);
      } else {
        encodedStrutStyle = null;
      }
      _constructor(
        style._encoded,
        encodedStrutStyle,/////style._strutStyle;
        style._fontFamily ?? '',
        strutFontFamilies,
        style._fontSize ?? 0,
        style._height ?? 0,
        style._ellipsis ?? '',
        _encodeLocale(style._locale)
      );
  }

///text.build

 void build(
    ui.ParagraphBuilder builder, {   //builder: strutStyle
    double textScaleFactor = 1.0,
    List<PlaceholderDimensions>? dimensions,
  }) {
    assert(debugAssertIsValid());
    final bool hasStyle = style != null;////text: style传递给 style: TextSpan text属性了
    if (hasStyle) {


      builder.pushStyle(style!.getTextStyle(textScaleFactor: textScaleFactor));


    }
    if (text != null) {
      try {
        

        builder.addText(text!); ////text: style传递给 style: TextSpan text属性了


      } on ArgumentError catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'painting library',
          context: ErrorDescription('while building a TextSpan'),
        ));
        // Use a Unicode replacement character as a substitute for invalid text.
        builder.addText('\uFFFD');
      }
    }
    if (children != null) {
      for (final InlineSpan child in children!) {
        assert(child != null);
        child.build(
          builder, ////builder: strutStyle
          textScaleFactor: textScaleFactor,
          dimensions: dimensions,
        );
      }
    }
    if (hasStyle) {
      builder.pop();
    }
  }


    //builder.addText(text!); ////text: style传递给 style: TextSpan text属性了
  void addText(String text) {
    final String? error = _addText(text);
    if (error != null) {
      throw ArgumentError(error);
    }
  }


//ParagraphBuilder builder
//builder.buildui.ParagraphBuilder


  @FfiNative<Void Function(Pointer<Void>, Handle)>('ParagraphBuilder::build')
  external void _build(Paragraph outParagraph);

style给TextSpan的text之外
strutStyle给ui.ParagraphBuilder builder

  text.build(builder, textScaleFactor: textScaleFactor, dimensions: _placeholderDimensions);
    builder.pushStyle(style!.getTextStyle(textScaleFactor: textScaleFactor));

      _paragraph = builder.build();
        @FfiNative<Void Function(Pointer<Void>, Handle)>('ParagraphBuilder::build')
  external void _build(Paragraph outParagraph);

textStyle和strutStyle

没有什么交集了。是两个独立的东西

2, style和defaultTextStyle,inherit

 defaultTextStyle.style.merge(style);
 // merge的意思就是 传得style如果有对应属性,就用传的,如果没有就用默认的
   TextStyle merge(TextStyle? other) {
    if (other == null) {
      return this;
    }
    if (!other.inherit) {
      return other;
    }
 
    return copyWith(
      color: other.color,
      backgroundColor: other.backgroundColor,
      fontSize: other.fontSize,
      fontWeight: other.fontWeight,
      fontStyle: other.fontStyle,
      letterSpacing: other.letterSpacing,
      wordSpacing: other.wordSpacing,
      textBaseline: other.textBaseline,
      height: other.height,
      leadingDistribution: other.leadingDistribution,
      locale: other.locale,
      foreground: other.foreground,
      background: other.background,
      shadows: other.shadows,
      fontFeatures: other.fontFeatures,
      fontVariations: other.fontVariations,
      decoration: other.decoration,
      decorationColor: other.decorationColor,
      decorationStyle: other.decorationStyle,
      decorationThickness: other.decorationThickness,
      debugLabel: mergedDebugLabel,
      fontFamily: other._fontFamily,
      fontFamilyFallback: other._fontFamilyFallback,
      package: other._package,
      overflow: other.overflow,
    );




    TextStyle copyWith({
    bool? inherit,
 
    FontStyle? fontStyle,
 
    String? fontFamily,
    List<String>? fontFamilyFallback,
 
  }) {
 
    return TextStyle(
    

      fontStyle: fontStyle ?? this.fontStyle,
 
      fontFamily: fontFamily ?? _fontFamily,
      fontFamilyFallback: fontFamilyFallback ?? _fontFamilyFallback,
 
    );
  }

3, 结论

textStyle和strutStyle 是两个比较独立的东西 最底层的代码flutter层看不到 对于文中前面提到的他们相同的属性fontSize,height,fontWeight,fontStyle,fontFamily,fontFamilyFallback如何使用的不清楚

应用其他网友的实验效果:
strutStyle对应类是StrutStyle,这个类是一个单独的文件,感觉应该挺重要
不过这个类看得不是非常懂,貌似是使用一个字体的骨架,但不用这个字体。
可以看出不同字体的基线是不同的,如果多种字体同时出现,未免会造成差别
使用统一的strutStyle可以让基线统一的同时又能保持字体的不同,大概就这个意思吧

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容