Unverified Commit 3efc517a authored by MH Johnson's avatar MH Johnson Committed by GitHub

[Widgets] Add DefaultTextHeightBehavior inherited widget. (#59196)

parent 64f42c0e
...@@ -203,6 +203,66 @@ class DefaultTextStyle extends InheritedTheme { ...@@ -203,6 +203,66 @@ class DefaultTextStyle extends InheritedTheme {
} }
} }
/// The [TextHeightBehavior] that will apply to descendant [Text] widgets which
/// have not explicitly set [Text.textHeightBehavior].
///
/// If there is a [DefaultTextStyle] with a non-null [DefaultTextStyle.textHeightBehavior]
/// below this widget, the [DefaultTextStyle.textHeightBehavior] will be used
/// over this widget's [TextHeightBehavior].
///
/// See also:
///
/// * [DefaultTextStyle], which defines a [TextStyle] to apply to descendant
/// [Text] widgets.
class DefaultTextHeightBehavior extends InheritedTheme {
/// Creates a default text height behavior for the given subtree.
///
/// The [textHeightBehavior] and [child] arguments are required and must not be null.
const DefaultTextHeightBehavior({
Key key,
@required this.textHeightBehavior,
@required Widget child,
}) : assert(textHeightBehavior != null),
assert(child != null),
super(key: key, child: child);
/// {@macro flutter.dart:ui.textHeightBehavior}
final TextHeightBehavior textHeightBehavior;
/// The closest instance of this class that encloses the given context.
///
/// If no such instance exists, this method will return `null`.
///
/// Typical usage is as follows:
///
/// ```dart
/// DefaultTextHeightBehavior defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
/// ```
static TextHeightBehavior of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<DefaultTextHeightBehavior>()?.textHeightBehavior;
}
@override
bool updateShouldNotify(DefaultTextHeightBehavior oldWidget) {
return textHeightBehavior != oldWidget.textHeightBehavior;
}
@override
Widget wrap(BuildContext context, Widget child) {
final DefaultTextHeightBehavior defaultTextHeightBehavior = context.findAncestorWidgetOfExactType<DefaultTextHeightBehavior>();
return identical(this, defaultTextHeightBehavior) ? child : DefaultTextHeightBehavior(
textHeightBehavior: textHeightBehavior,
child: child,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<ui.TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
}
}
/// A run of text with a single style. /// A run of text with a single style.
/// ///
/// The [Text] widget displays a string of text with single style. The string /// The [Text] widget displays a string of text with single style. The string
...@@ -451,7 +511,7 @@ class Text extends StatelessWidget { ...@@ -451,7 +511,7 @@ class Text extends StatelessWidget {
maxLines: maxLines ?? defaultTextStyle.maxLines, maxLines: maxLines ?? defaultTextStyle.maxLines,
strutStyle: strutStyle, strutStyle: strutStyle,
textWidthBasis: textWidthBasis ?? defaultTextStyle.textWidthBasis, textWidthBasis: textWidthBasis ?? defaultTextStyle.textWidthBasis,
textHeightBehavior: textHeightBehavior ?? defaultTextStyle.textHeightBehavior, textHeightBehavior: textHeightBehavior ?? defaultTextStyle.textHeightBehavior ?? DefaultTextHeightBehavior.of(context),
text: TextSpan( text: TextSpan(
style: effectiveTextStyle, style: effectiveTextStyle,
text: data, text: data,
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show TextHeightBehavior;
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/painting.dart';
void main() {
testWidgets('Text widget parameter takes precedence over DefaultTextHeightBehavior', (WidgetTester tester) async {
const TextHeightBehavior behavior1 = TextHeightBehavior(
applyHeightToLastDescent: false,
applyHeightToFirstAscent: false,
);
const TextHeightBehavior behavior2 = TextHeightBehavior(
applyHeightToLastDescent: true,
applyHeightToFirstAscent: false,
);
await tester.pumpWidget(
const DefaultTextHeightBehavior(
textHeightBehavior: behavior2,
child: Text(
'Hello',
textDirection: TextDirection.ltr,
textHeightBehavior: behavior1,
),
),
);
final RichText text = tester.firstWidget(find.byType(RichText));
expect(text, isNotNull);
expect(text.textHeightBehavior, behavior1);
});
testWidgets('DefaultTextStyle.textHeightBehavior takes precedence over DefaultTextHeightBehavior ', (WidgetTester tester) async {
const TextHeightBehavior behavior1 = TextHeightBehavior(
applyHeightToLastDescent: false,
applyHeightToFirstAscent: false,
);
const TextHeightBehavior behavior2 = TextHeightBehavior(
applyHeightToLastDescent: true,
applyHeightToFirstAscent: false,
);
await tester.pumpWidget(
const DefaultTextStyle(
style: TextStyle(),
textHeightBehavior: behavior1,
child: DefaultTextHeightBehavior(
textHeightBehavior: behavior2,
child: Text(
'Hello',
textDirection: TextDirection.ltr,
),
),
),
);
RichText text = tester.firstWidget(find.byType(RichText));
expect(text, isNotNull);
expect(text.textHeightBehavior, behavior1);
await tester.pumpWidget(
const DefaultTextHeightBehavior(
textHeightBehavior: behavior2,
child: DefaultTextStyle(
style: TextStyle(),
textHeightBehavior: behavior1,
child: Text(
'Hello',
textDirection: TextDirection.ltr,
),
),
),
);
text = tester.firstWidget(find.byType(RichText));
expect(text, isNotNull);
expect(text.textHeightBehavior, behavior1);
});
testWidgets('DefaultTextHeightBehavior changes propagate to Text', (WidgetTester tester) async {
const Text textWidget = Text('Hello', textDirection: TextDirection.ltr);
const TextHeightBehavior behavior1 = TextHeightBehavior(
applyHeightToLastDescent: false,
applyHeightToFirstAscent: false,
);
const TextHeightBehavior behavior2 = TextHeightBehavior(
applyHeightToLastDescent: false,
applyHeightToFirstAscent: false,
);
await tester.pumpWidget(const DefaultTextHeightBehavior(
textHeightBehavior: behavior1,
child: textWidget,
));
RichText text = tester.firstWidget(find.byType(RichText));
expect(text, isNotNull);
expect(text.textHeightBehavior, behavior1);
await tester.pumpWidget(const DefaultTextHeightBehavior(
textHeightBehavior: behavior2,
child: textWidget,
));
text = tester.firstWidget(find.byType(RichText));
expect(text, isNotNull);
expect(text.textHeightBehavior, behavior2);
});
testWidgets('DefaultTextHeightBehavior.of(context) returns null if no '
'DefaultTextHeightBehavior widget in tree', (WidgetTester tester) async {
const Text textWidget = Text('Hello', textDirection: TextDirection.ltr);
TextHeightBehavior textHeightBehavior;
await tester.pumpWidget(Builder(
builder: (BuildContext context) {
textHeightBehavior = DefaultTextHeightBehavior.of(context);
return textWidget;
},
));
expect(textHeightBehavior, isNull);
final RichText text = tester.firstWidget(find.byType(RichText));
expect(text, isNotNull);
expect(text.textHeightBehavior, isNull);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment