2024-03-07 flutter StrutStyle和Te
2024-03-06 本文已影响0人
我是小胡胡分胡
StrutStyle和TextStyle区别
WX20240307-121045@2x.png1,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可以让基线统一的同时又能保持字体的不同,大概就这个意思吧