Add margins to tooltips (#36963)
* Add margin parameter to tooltips * Improve tooltip tests to find the tooltip's `Container` instead of arbitrary number of parent calls
This commit is contained in:
parent
e4ebcdf6f4
commit
c1a118bcc3
@ -51,6 +51,7 @@ class Tooltip extends StatefulWidget {
|
|||||||
@required this.message,
|
@required this.message,
|
||||||
this.height,
|
this.height,
|
||||||
this.padding,
|
this.padding,
|
||||||
|
this.margin,
|
||||||
this.verticalOffset,
|
this.verticalOffset,
|
||||||
this.preferBelow,
|
this.preferBelow,
|
||||||
this.excludeFromSemantics,
|
this.excludeFromSemantics,
|
||||||
@ -75,6 +76,19 @@ class Tooltip extends StatefulWidget {
|
|||||||
/// Defaults to 16.0 logical pixels in each direction.
|
/// Defaults to 16.0 logical pixels in each direction.
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
|
/// The empty space that surrounds the tooltip.
|
||||||
|
///
|
||||||
|
/// Defines the tooltip's outer [Container.margin]. By default, a
|
||||||
|
/// long tooltip will span the width of its window. If long enough,
|
||||||
|
/// a tooltip might also span the window's height. This property allows
|
||||||
|
/// one to define how much space the tooltip must be inset from the edges
|
||||||
|
/// of their display window.
|
||||||
|
///
|
||||||
|
/// If this property is null, then [TooltipThemeData.margin] is used.
|
||||||
|
/// If [TooltipThemeData.margin] is also null, the default margin is
|
||||||
|
/// 0.0 logical pixels on all sides.
|
||||||
|
final EdgeInsetsGeometry margin;
|
||||||
|
|
||||||
/// The vertical gap between the widget and the displayed tooltip.
|
/// The vertical gap between the widget and the displayed tooltip.
|
||||||
///
|
///
|
||||||
/// When [preferBelow] is set to true and tooltips have sufficient space to
|
/// When [preferBelow] is set to true and tooltips have sufficient space to
|
||||||
@ -145,6 +159,7 @@ class Tooltip extends StatefulWidget {
|
|||||||
properties.add(StringProperty('message', message, showName: false));
|
properties.add(StringProperty('message', message, showName: false));
|
||||||
properties.add(DoubleProperty('height', height, defaultValue: null));
|
properties.add(DoubleProperty('height', height, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
|
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
|
||||||
|
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('margin', margin, defaultValue: null));
|
||||||
properties.add(DoubleProperty('vertical offset', verticalOffset, defaultValue: null));
|
properties.add(DoubleProperty('vertical offset', verticalOffset, defaultValue: null));
|
||||||
properties.add(FlagProperty('position', value: preferBelow, ifTrue: 'below', ifFalse: 'above', showName: true, defaultValue: null));
|
properties.add(FlagProperty('position', value: preferBelow, ifTrue: 'below', ifFalse: 'above', showName: true, defaultValue: null));
|
||||||
properties.add(FlagProperty('semantics', value: excludeFromSemantics, ifTrue: 'excluded', showName: true, defaultValue: null));
|
properties.add(FlagProperty('semantics', value: excludeFromSemantics, ifTrue: 'excluded', showName: true, defaultValue: null));
|
||||||
@ -158,6 +173,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
static const double _defaultVerticalOffset = 24.0;
|
static const double _defaultVerticalOffset = 24.0;
|
||||||
static const bool _defaultPreferBelow = true;
|
static const bool _defaultPreferBelow = true;
|
||||||
static const EdgeInsetsGeometry _defaultPadding = EdgeInsets.symmetric(horizontal: 16.0);
|
static const EdgeInsetsGeometry _defaultPadding = EdgeInsets.symmetric(horizontal: 16.0);
|
||||||
|
static const EdgeInsetsGeometry _defaultMargin = EdgeInsets.all(0.0);
|
||||||
static const Duration _fadeInDuration = Duration(milliseconds: 150);
|
static const Duration _fadeInDuration = Duration(milliseconds: 150);
|
||||||
static const Duration _fadeOutDuration = Duration(milliseconds: 75);
|
static const Duration _fadeOutDuration = Duration(milliseconds: 75);
|
||||||
static const Duration _defaultShowDuration = Duration(milliseconds: 1500);
|
static const Duration _defaultShowDuration = Duration(milliseconds: 1500);
|
||||||
@ -166,6 +182,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
|
|
||||||
double height;
|
double height;
|
||||||
EdgeInsetsGeometry padding;
|
EdgeInsetsGeometry padding;
|
||||||
|
EdgeInsetsGeometry margin;
|
||||||
Decoration decoration;
|
Decoration decoration;
|
||||||
TextStyle textStyle;
|
TextStyle textStyle;
|
||||||
double verticalOffset;
|
double verticalOffset;
|
||||||
@ -273,6 +290,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
message: widget.message,
|
message: widget.message,
|
||||||
height: height,
|
height: height,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
|
margin: margin,
|
||||||
decoration: decoration,
|
decoration: decoration,
|
||||||
textStyle: textStyle,
|
textStyle: textStyle,
|
||||||
animation: CurvedAnimation(
|
animation: CurvedAnimation(
|
||||||
@ -360,6 +378,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
|
|
||||||
height = widget.height ?? tooltipTheme.height ?? _defaultTooltipHeight;
|
height = widget.height ?? tooltipTheme.height ?? _defaultTooltipHeight;
|
||||||
padding = widget.padding ?? tooltipTheme.padding ?? _defaultPadding;
|
padding = widget.padding ?? tooltipTheme.padding ?? _defaultPadding;
|
||||||
|
margin = widget.margin ?? tooltipTheme.margin ?? _defaultMargin;
|
||||||
verticalOffset = widget.verticalOffset ?? tooltipTheme.verticalOffset ?? _defaultVerticalOffset;
|
verticalOffset = widget.verticalOffset ?? tooltipTheme.verticalOffset ?? _defaultVerticalOffset;
|
||||||
preferBelow = widget.preferBelow ?? tooltipTheme.preferBelow ?? _defaultPreferBelow;
|
preferBelow = widget.preferBelow ?? tooltipTheme.preferBelow ?? _defaultPreferBelow;
|
||||||
excludeFromSemantics = widget.excludeFromSemantics ?? tooltipTheme.excludeFromSemantics ?? _defaultExcludeFromSemantics;
|
excludeFromSemantics = widget.excludeFromSemantics ?? tooltipTheme.excludeFromSemantics ?? _defaultExcludeFromSemantics;
|
||||||
@ -447,6 +466,7 @@ class _TooltipOverlay extends StatelessWidget {
|
|||||||
this.message,
|
this.message,
|
||||||
this.height,
|
this.height,
|
||||||
this.padding,
|
this.padding,
|
||||||
|
this.margin,
|
||||||
this.decoration,
|
this.decoration,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
this.animation,
|
this.animation,
|
||||||
@ -458,6 +478,7 @@ class _TooltipOverlay extends StatelessWidget {
|
|||||||
final String message;
|
final String message;
|
||||||
final double height;
|
final double height;
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
final EdgeInsetsGeometry margin;
|
||||||
final Decoration decoration;
|
final Decoration decoration;
|
||||||
final TextStyle textStyle;
|
final TextStyle textStyle;
|
||||||
final Animation<double> animation;
|
final Animation<double> animation;
|
||||||
@ -482,6 +503,7 @@ class _TooltipOverlay extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
decoration: decoration,
|
decoration: decoration,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
|
margin: margin,
|
||||||
child: Center(
|
child: Center(
|
||||||
widthFactor: 1.0,
|
widthFactor: 1.0,
|
||||||
heightFactor: 1.0,
|
heightFactor: 1.0,
|
||||||
|
@ -28,6 +28,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
const TooltipThemeData({
|
const TooltipThemeData({
|
||||||
this.height,
|
this.height,
|
||||||
this.padding,
|
this.padding,
|
||||||
|
this.margin,
|
||||||
this.verticalOffset,
|
this.verticalOffset,
|
||||||
this.preferBelow,
|
this.preferBelow,
|
||||||
this.excludeFromSemantics,
|
this.excludeFromSemantics,
|
||||||
@ -43,6 +44,9 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
/// If provided, the amount of space by which to inset [Tooltip.child].
|
/// If provided, the amount of space by which to inset [Tooltip.child].
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
|
/// If provided, the amount of empty space to surround the [Tooltip].
|
||||||
|
final EdgeInsetsGeometry margin;
|
||||||
|
|
||||||
/// The vertical gap between the widget and the displayed tooltip.
|
/// The vertical gap between the widget and the displayed tooltip.
|
||||||
///
|
///
|
||||||
/// When [preferBelow] is set to true and tooltips have sufficient space to
|
/// When [preferBelow] is set to true and tooltips have sufficient space to
|
||||||
@ -84,6 +88,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
TooltipThemeData copyWith({
|
TooltipThemeData copyWith({
|
||||||
double height,
|
double height,
|
||||||
EdgeInsetsGeometry padding,
|
EdgeInsetsGeometry padding,
|
||||||
|
EdgeInsetsGeometry margin,
|
||||||
double verticalOffset,
|
double verticalOffset,
|
||||||
bool preferBelow,
|
bool preferBelow,
|
||||||
bool excludeFromSemantics,
|
bool excludeFromSemantics,
|
||||||
@ -95,6 +100,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
return TooltipThemeData(
|
return TooltipThemeData(
|
||||||
height: height ?? this.height,
|
height: height ?? this.height,
|
||||||
padding: padding ?? this.padding,
|
padding: padding ?? this.padding,
|
||||||
|
margin: margin ?? this.margin,
|
||||||
verticalOffset: verticalOffset ?? this.verticalOffset,
|
verticalOffset: verticalOffset ?? this.verticalOffset,
|
||||||
preferBelow: preferBelow ?? this.preferBelow,
|
preferBelow: preferBelow ?? this.preferBelow,
|
||||||
excludeFromSemantics: excludeFromSemantics ?? this.excludeFromSemantics,
|
excludeFromSemantics: excludeFromSemantics ?? this.excludeFromSemantics,
|
||||||
@ -117,6 +123,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
return TooltipThemeData(
|
return TooltipThemeData(
|
||||||
height: lerpDouble(a?.height, b?.height, t),
|
height: lerpDouble(a?.height, b?.height, t),
|
||||||
padding: EdgeInsets.lerp(a?.padding, b?.padding, t),
|
padding: EdgeInsets.lerp(a?.padding, b?.padding, t),
|
||||||
|
margin: EdgeInsets.lerp(a?.margin, b?.margin, t),
|
||||||
verticalOffset: lerpDouble(a?.verticalOffset, b?.verticalOffset, t),
|
verticalOffset: lerpDouble(a?.verticalOffset, b?.verticalOffset, t),
|
||||||
preferBelow: t < 0.5 ? a.preferBelow: b.preferBelow,
|
preferBelow: t < 0.5 ? a.preferBelow: b.preferBelow,
|
||||||
excludeFromSemantics: t < 0.5 ? a.excludeFromSemantics : b.excludeFromSemantics,
|
excludeFromSemantics: t < 0.5 ? a.excludeFromSemantics : b.excludeFromSemantics,
|
||||||
@ -130,6 +137,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
return hashValues(
|
return hashValues(
|
||||||
height,
|
height,
|
||||||
padding,
|
padding,
|
||||||
|
margin,
|
||||||
verticalOffset,
|
verticalOffset,
|
||||||
preferBelow,
|
preferBelow,
|
||||||
excludeFromSemantics,
|
excludeFromSemantics,
|
||||||
@ -149,6 +157,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
final TooltipThemeData typedOther = other;
|
final TooltipThemeData typedOther = other;
|
||||||
return typedOther.height == height
|
return typedOther.height == height
|
||||||
&& typedOther.padding == padding
|
&& typedOther.padding == padding
|
||||||
|
&& typedOther.margin == margin
|
||||||
&& typedOther.verticalOffset == verticalOffset
|
&& typedOther.verticalOffset == verticalOffset
|
||||||
&& typedOther.preferBelow == preferBelow
|
&& typedOther.preferBelow == preferBelow
|
||||||
&& typedOther.excludeFromSemantics == excludeFromSemantics
|
&& typedOther.excludeFromSemantics == excludeFromSemantics
|
||||||
@ -163,6 +172,7 @@ class TooltipThemeData extends Diagnosticable {
|
|||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
properties.add(DoubleProperty('height', height, defaultValue: null));
|
properties.add(DoubleProperty('height', height, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
|
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
|
||||||
|
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('margin', margin, defaultValue: null));
|
||||||
properties.add(DoubleProperty('vertical offset', verticalOffset, defaultValue: null));
|
properties.add(DoubleProperty('vertical offset', verticalOffset, defaultValue: null));
|
||||||
properties.add(FlagProperty('position', value: preferBelow, ifTrue: 'below', ifFalse: 'above', showName: true, defaultValue: null));
|
properties.add(FlagProperty('position', value: preferBelow, ifTrue: 'below', ifFalse: 'above', showName: true, defaultValue: null));
|
||||||
properties.add(FlagProperty('semantics', value: excludeFromSemantics, ifTrue: 'excluded', showName: true, defaultValue: null));
|
properties.add(FlagProperty('semantics', value: excludeFromSemantics, ifTrue: 'excluded', showName: true, defaultValue: null));
|
||||||
@ -208,6 +218,7 @@ class TooltipTheme extends InheritedWidget {
|
|||||||
Key key,
|
Key key,
|
||||||
double height,
|
double height,
|
||||||
EdgeInsetsGeometry padding,
|
EdgeInsetsGeometry padding,
|
||||||
|
EdgeInsetsGeometry margin,
|
||||||
double verticalOffset,
|
double verticalOffset,
|
||||||
bool preferBelow,
|
bool preferBelow,
|
||||||
bool excludeFromSemantics,
|
bool excludeFromSemantics,
|
||||||
@ -219,6 +230,7 @@ class TooltipTheme extends InheritedWidget {
|
|||||||
}) : data = TooltipThemeData(
|
}) : data = TooltipThemeData(
|
||||||
height: height,
|
height: height,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
|
margin: margin,
|
||||||
verticalOffset: verticalOffset,
|
verticalOffset: verticalOffset,
|
||||||
preferBelow: preferBelow,
|
preferBelow: preferBelow,
|
||||||
excludeFromSemantics: excludeFromSemantics,
|
excludeFromSemantics: excludeFromSemantics,
|
||||||
|
@ -32,6 +32,13 @@ import 'feedback_tester.dart';
|
|||||||
|
|
||||||
const String tooltipText = 'TIP';
|
const String tooltipText = 'TIP';
|
||||||
|
|
||||||
|
Finder _findTooltipContainer(String tooltipText) {
|
||||||
|
return find.ancestor(
|
||||||
|
of: find.text(tooltipText),
|
||||||
|
matching: find.byType(Container),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Does tooltip end up in the right place - center', (WidgetTester tester) async {
|
testWidgets('Does tooltip end up in the right place - center', (WidgetTester tester) async {
|
||||||
final GlobalKey key = GlobalKey();
|
final GlobalKey key = GlobalKey();
|
||||||
@ -80,8 +87,9 @@ void main() {
|
|||||||
* *
|
* *
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent.parent.parent.parent.parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
final Offset tipInGlobal = tip.localToGlobal(tip.size.topCenter(Offset.zero));
|
final Offset tipInGlobal = tip.localToGlobal(tip.size.topCenter(Offset.zero));
|
||||||
// The exact position of the left side depends on the font the test framework
|
// The exact position of the left side depends on the font the test framework
|
||||||
// happens to pick, so we don't test that.
|
// happens to pick, so we don't test that.
|
||||||
@ -136,7 +144,9 @@ void main() {
|
|||||||
* *
|
* *
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent.parent.parent.parent.parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(24.0)); // 14.0 height + 5.0 padding * 2 (top, bottom)
|
expect(tip.size.height, equals(24.0)); // 14.0 height + 5.0 padding * 2 (top, bottom)
|
||||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)), equals(const Offset(10.0, 20.0)));
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)), equals(const Offset(10.0, 20.0)));
|
||||||
}, skip: isBrowser);
|
}, skip: isBrowser);
|
||||||
@ -189,7 +199,9 @@ void main() {
|
|||||||
* *
|
* *
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(100.0));
|
expect(tip.size.height, equals(100.0));
|
||||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(100.0));
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(100.0));
|
||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(200.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(200.0));
|
||||||
@ -254,7 +266,9 @@ void main() {
|
|||||||
* * }- 10.0 margin
|
* * }- 10.0 margin
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(190.0));
|
expect(tip.size.height, equals(190.0));
|
||||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(399.0));
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(399.0));
|
||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(589.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(589.0));
|
||||||
@ -307,7 +321,9 @@ void main() {
|
|||||||
* * }- 10.0 margin
|
* * }- 10.0 margin
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(190.0));
|
expect(tip.size.height, equals(190.0));
|
||||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(400.0));
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(400.0));
|
||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(590.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(590.0));
|
||||||
@ -361,7 +377,9 @@ void main() {
|
|||||||
* * }-10.0 margin
|
* * }-10.0 margin
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(14.0));
|
expect(tip.size.height, equals(14.0));
|
||||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
||||||
@ -416,13 +434,73 @@ void main() {
|
|||||||
* * }-10.0 margin
|
* * }-10.0 margin
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(14.0));
|
expect(tip.size.height, equals(14.0));
|
||||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(324.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(324.0));
|
||||||
}, skip: isBrowser);
|
}, skip: isBrowser);
|
||||||
|
|
||||||
|
testWidgets('Custom tooltip margin', (WidgetTester tester) async {
|
||||||
|
const double _customMarginValue = 10.0;
|
||||||
|
final GlobalKey key = GlobalKey();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: Overlay(
|
||||||
|
initialEntries: <OverlayEntry>[
|
||||||
|
OverlayEntry(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Tooltip(
|
||||||
|
key: key,
|
||||||
|
message: tooltipText,
|
||||||
|
padding: const EdgeInsets.all(0.0),
|
||||||
|
margin: const EdgeInsets.all(_customMarginValue),
|
||||||
|
child: Container(
|
||||||
|
width: 0.0,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
||||||
|
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||||
|
|
||||||
|
final Offset topLeftTipInGlobal = tester.getTopLeft(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
|
final Offset topLeftTooltipContentInGlobal = tester.getTopLeft(find.text(tooltipText));
|
||||||
|
expect(topLeftTooltipContentInGlobal.dx, topLeftTipInGlobal.dx + _customMarginValue);
|
||||||
|
expect(topLeftTooltipContentInGlobal.dy, topLeftTipInGlobal.dy + _customMarginValue);
|
||||||
|
|
||||||
|
final Offset topRightTipInGlobal = tester.getTopRight(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
|
final Offset topRightTooltipContentInGlobal = tester.getTopRight(find.text(tooltipText));
|
||||||
|
expect(topRightTooltipContentInGlobal.dx, topRightTipInGlobal.dx - _customMarginValue);
|
||||||
|
expect(topRightTooltipContentInGlobal.dy, topRightTipInGlobal.dy + _customMarginValue);
|
||||||
|
|
||||||
|
final Offset bottomLeftTipInGlobal = tester.getBottomLeft(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
|
final Offset bottomLeftTooltipContentInGlobal = tester.getBottomLeft(find.text(tooltipText));
|
||||||
|
expect(bottomLeftTooltipContentInGlobal.dx, bottomLeftTipInGlobal.dx + _customMarginValue);
|
||||||
|
expect(bottomLeftTooltipContentInGlobal.dy, bottomLeftTipInGlobal.dy - _customMarginValue);
|
||||||
|
|
||||||
|
final Offset bottomRightTipInGlobal = tester.getBottomRight(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
|
final Offset bottomRightTooltipContentInGlobal = tester.getBottomRight(find.text(tooltipText));
|
||||||
|
expect(bottomRightTooltipContentInGlobal.dx, bottomRightTipInGlobal.dx - _customMarginValue);
|
||||||
|
expect(bottomRightTooltipContentInGlobal.dy, bottomRightTipInGlobal.dy - _customMarginValue);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Default tooltip message textStyle - light', (WidgetTester tester) async {
|
testWidgets('Default tooltip message textStyle - light', (WidgetTester tester) async {
|
||||||
final GlobalKey key = GlobalKey();
|
final GlobalKey key = GlobalKey();
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
@ -524,8 +602,9 @@ void main() {
|
|||||||
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
||||||
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent.parent.parent.parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(32.0));
|
expect(tip.size.height, equals(32.0));
|
||||||
expect(tip.size.width, equals(74.0));
|
expect(tip.size.width, equals(74.0));
|
||||||
expect(tip, paints..rrect(
|
expect(tip, paints..rrect(
|
||||||
@ -565,8 +644,9 @@ void main() {
|
|||||||
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
||||||
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent.parent.parent.parent;
|
final RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(32.0));
|
expect(tip.size.height, equals(32.0));
|
||||||
expect(tip.size.width, equals(74.0));
|
expect(tip.size.width, equals(74.0));
|
||||||
expect(tip, paints..path(
|
expect(tip, paints..path(
|
||||||
@ -782,14 +862,18 @@ void main() {
|
|||||||
await tester.longPress(find.byType(Tooltip));
|
await tester.longPress(find.byType(Tooltip));
|
||||||
expect(find.text(tooltipText), findsOneWidget);
|
expect(find.text(tooltipText), findsOneWidget);
|
||||||
expect(tester.getSize(find.text(tooltipText)), equals(const Size(42.0, 14.0)));
|
expect(tester.getSize(find.text(tooltipText)), equals(const Size(42.0, 14.0)));
|
||||||
RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
RenderBox tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(32.0));
|
expect(tip.size.height, equals(32.0));
|
||||||
|
|
||||||
await tester.pumpWidget(buildApp(tooltipText, textScaleFactor: 4.0));
|
await tester.pumpWidget(buildApp(tooltipText, textScaleFactor: 4.0));
|
||||||
await tester.longPress(find.byType(Tooltip));
|
await tester.longPress(find.byType(Tooltip));
|
||||||
expect(find.text(tooltipText), findsOneWidget);
|
expect(find.text(tooltipText), findsOneWidget);
|
||||||
expect(tester.getSize(find.text(tooltipText)), equals(const Size(168.0, 56.0)));
|
expect(tester.getSize(find.text(tooltipText)), equals(const Size(168.0, 56.0)));
|
||||||
tip = tester.renderObject(find.text(tooltipText)).parent;
|
tip = tester.renderObject(
|
||||||
|
_findTooltipContainer(tooltipText),
|
||||||
|
);
|
||||||
expect(tip.size.height, equals(56.0));
|
expect(tip.size.height, equals(56.0));
|
||||||
}, skip: isBrowser);
|
}, skip: isBrowser);
|
||||||
|
|
||||||
@ -953,6 +1037,7 @@ void main() {
|
|||||||
waitDuration: Duration(seconds: 1),
|
waitDuration: Duration(seconds: 1),
|
||||||
showDuration: Duration(seconds: 2),
|
showDuration: Duration(seconds: 2),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
|
margin: EdgeInsets.all(5.0),
|
||||||
height: 100.0,
|
height: 100.0,
|
||||||
excludeFromSemantics: true,
|
excludeFromSemantics: true,
|
||||||
preferBelow: false,
|
preferBelow: false,
|
||||||
@ -967,6 +1052,7 @@ void main() {
|
|||||||
'"message"',
|
'"message"',
|
||||||
'height: 100.0',
|
'height: 100.0',
|
||||||
'padding: EdgeInsets.zero',
|
'padding: EdgeInsets.zero',
|
||||||
|
'margin: EdgeInsets.all(5.0)',
|
||||||
'vertical offset: 50.0',
|
'vertical offset: 50.0',
|
||||||
'position: above',
|
'position: above',
|
||||||
'semantics: excluded',
|
'semantics: excluded',
|
||||||
|
@ -28,6 +28,7 @@ import '../widgets/semantics_tester.dart';
|
|||||||
// production code.
|
// production code.
|
||||||
|
|
||||||
const String tooltipText = 'TIP';
|
const String tooltipText = 'TIP';
|
||||||
|
const double _customPaddingValue = 10.0;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('TooltipThemeData copyWith, ==, hashCode basics', () {
|
test('TooltipThemeData copyWith, ==, hashCode basics', () {
|
||||||
@ -460,6 +461,118 @@ void main() {
|
|||||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(590.0));
|
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(590.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Tooltip margin - ThemeData', (WidgetTester tester) async {
|
||||||
|
final GlobalKey key = GlobalKey();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: Overlay(
|
||||||
|
initialEntries: <OverlayEntry>[
|
||||||
|
OverlayEntry(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
tooltipTheme: const TooltipThemeData(
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
margin: EdgeInsets.all(_customPaddingValue),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
|
key: key,
|
||||||
|
message: tooltipText,
|
||||||
|
child: Container(
|
||||||
|
width: 0.0,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
||||||
|
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||||
|
|
||||||
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent.parent.parent.parent.parent;
|
||||||
|
final RenderBox tooltipContent = tester.renderObject(find.text(tooltipText));
|
||||||
|
|
||||||
|
final Offset topLeftTipInGlobal = tip.localToGlobal(tip.size.topLeft(Offset.zero));
|
||||||
|
final Offset topLeftTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.topLeft(Offset.zero));
|
||||||
|
expect(topLeftTooltipContentInGlobal.dx, topLeftTipInGlobal.dx + _customPaddingValue);
|
||||||
|
expect(topLeftTooltipContentInGlobal.dy, topLeftTipInGlobal.dy + _customPaddingValue);
|
||||||
|
|
||||||
|
final Offset topRightTipInGlobal = tip.localToGlobal(tip.size.topRight(Offset.zero));
|
||||||
|
final Offset topRightTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.topRight(Offset.zero));
|
||||||
|
expect(topRightTooltipContentInGlobal.dx, topRightTipInGlobal.dx - _customPaddingValue);
|
||||||
|
expect(topRightTooltipContentInGlobal.dy, topRightTipInGlobal.dy + _customPaddingValue);
|
||||||
|
|
||||||
|
final Offset bottomLeftTipInGlobal = tip.localToGlobal(tip.size.bottomLeft(Offset.zero));
|
||||||
|
final Offset bottomLeftTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.bottomLeft(Offset.zero));
|
||||||
|
expect(bottomLeftTooltipContentInGlobal.dx, bottomLeftTipInGlobal.dx + _customPaddingValue);
|
||||||
|
expect(bottomLeftTooltipContentInGlobal.dy, bottomLeftTipInGlobal.dy - _customPaddingValue);
|
||||||
|
|
||||||
|
final Offset bottomRightTipInGlobal = tip.localToGlobal(tip.size.bottomRight(Offset.zero));
|
||||||
|
final Offset bottomRightTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.bottomRight(Offset.zero));
|
||||||
|
expect(bottomRightTooltipContentInGlobal.dx, bottomRightTipInGlobal.dx - _customPaddingValue);
|
||||||
|
expect(bottomRightTooltipContentInGlobal.dy, bottomRightTipInGlobal.dy - _customPaddingValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Tooltip margin - TooltipTheme', (WidgetTester tester) async {
|
||||||
|
final GlobalKey key = GlobalKey();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: Overlay(
|
||||||
|
initialEntries: <OverlayEntry>[
|
||||||
|
OverlayEntry(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return TooltipTheme(
|
||||||
|
padding: const EdgeInsets.all(0.0),
|
||||||
|
margin: const EdgeInsets.all(_customPaddingValue),
|
||||||
|
child: Tooltip(
|
||||||
|
key: key,
|
||||||
|
message: tooltipText,
|
||||||
|
child: Container(
|
||||||
|
width: 0.0,
|
||||||
|
height: 0.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
|
||||||
|
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||||
|
|
||||||
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent.parent.parent.parent.parent;
|
||||||
|
final RenderBox tooltipContent = tester.renderObject(find.text(tooltipText));
|
||||||
|
|
||||||
|
final Offset topLeftTipInGlobal = tip.localToGlobal(tip.size.topLeft(Offset.zero));
|
||||||
|
final Offset topLeftTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.topLeft(Offset.zero));
|
||||||
|
expect(topLeftTooltipContentInGlobal.dx, topLeftTipInGlobal.dx + _customPaddingValue);
|
||||||
|
expect(topLeftTooltipContentInGlobal.dy, topLeftTipInGlobal.dy + _customPaddingValue);
|
||||||
|
|
||||||
|
final Offset topRightTipInGlobal = tip.localToGlobal(tip.size.topRight(Offset.zero));
|
||||||
|
final Offset topRightTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.topRight(Offset.zero));
|
||||||
|
expect(topRightTooltipContentInGlobal.dx, topRightTipInGlobal.dx - _customPaddingValue);
|
||||||
|
expect(topRightTooltipContentInGlobal.dy, topRightTipInGlobal.dy + _customPaddingValue);
|
||||||
|
|
||||||
|
final Offset bottomLeftTipInGlobal = tip.localToGlobal(tip.size.bottomLeft(Offset.zero));
|
||||||
|
final Offset bottomLeftTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.bottomLeft(Offset.zero));
|
||||||
|
expect(bottomLeftTooltipContentInGlobal.dx, bottomLeftTipInGlobal.dx + _customPaddingValue);
|
||||||
|
expect(bottomLeftTooltipContentInGlobal.dy, bottomLeftTipInGlobal.dy - _customPaddingValue);
|
||||||
|
|
||||||
|
final Offset bottomRightTipInGlobal = tip.localToGlobal(tip.size.bottomRight(Offset.zero));
|
||||||
|
final Offset bottomRightTooltipContentInGlobal = tooltipContent.localToGlobal(tooltipContent.size.bottomRight(Offset.zero));
|
||||||
|
expect(bottomRightTooltipContentInGlobal.dx, bottomRightTipInGlobal.dx - _customPaddingValue);
|
||||||
|
expect(bottomRightTooltipContentInGlobal.dy, bottomRightTipInGlobal.dy - _customPaddingValue);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Tooltip message textStyle - ThemeData.tooltipTheme', (WidgetTester tester) async {
|
testWidgets('Tooltip message textStyle - ThemeData.tooltipTheme', (WidgetTester tester) async {
|
||||||
final GlobalKey key = GlobalKey();
|
final GlobalKey key = GlobalKey();
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
@ -641,7 +754,7 @@ void main() {
|
|||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.ancestor(
|
final RenderBox tip = tester.renderObject(find.ancestor(
|
||||||
of: find.text(tooltipText),
|
of: find.text(tooltipText),
|
||||||
matching: find.byType(Padding),
|
matching: find.byType(Padding).first, // select [Tooltip.padding] instead of [Tooltip.margin]
|
||||||
));
|
));
|
||||||
final RenderBox content = tester.renderObject(find.ancestor(
|
final RenderBox content = tester.renderObject(find.ancestor(
|
||||||
of: find.text(tooltipText),
|
of: find.text(tooltipText),
|
||||||
@ -684,7 +797,7 @@ void main() {
|
|||||||
|
|
||||||
final RenderBox tip = tester.renderObject(find.ancestor(
|
final RenderBox tip = tester.renderObject(find.ancestor(
|
||||||
of: find.text(tooltipText),
|
of: find.text(tooltipText),
|
||||||
matching: find.byType(Padding),
|
matching: find.byType(Padding).first, // select [Tooltip.padding] instead of [Tooltip.margin]
|
||||||
));
|
));
|
||||||
final RenderBox content = tester.renderObject(find.ancestor(
|
final RenderBox content = tester.renderObject(find.ancestor(
|
||||||
of: find.text(tooltipText),
|
of: find.text(tooltipText),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user