2024-03-07 flutter StrutStyle和Te

2024-03-06  本文已影响0人  我是小胡胡分胡

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可以让基线统一的同时又能保持字体的不同,大概就这个意思吧

上一篇下一篇

猜你喜欢

热点阅读