Unverified Commit 48f08e3d authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

IgnoreBaseline widget (#131220)

Fixes https://github.com/flutter/flutter/issues/7037
parent 22406493
...@@ -916,7 +916,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -916,7 +916,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
while (child != null) { while (child != null) {
assert(() { assert(() {
if (textBaseline == null) { if (textBaseline == null) {
throw FlutterError('To use FlexAlignItems.baseline, you must also specify which baseline to use using the "baseline" argument.'); throw FlutterError('To use CrossAxisAlignment.baseline, you must also specify which baseline to use using the "textBaseline" argument.');
} }
return true; return true;
}()); }());
......
...@@ -842,6 +842,19 @@ class RenderIntrinsicHeight extends RenderProxyBox { ...@@ -842,6 +842,19 @@ class RenderIntrinsicHeight extends RenderProxyBox {
} }
} }
/// Excludes the child from baseline computations in the parent.
class RenderIgnoreBaseline extends RenderProxyBox {
/// Create a render object that causes the parent to ignore the child for baseline computations.
RenderIgnoreBaseline({
RenderBox? child,
}) : super(child);
@override
double? computeDistanceToActualBaseline(TextBaseline baseline) {
return null;
}
}
/// Makes its child partially transparent. /// Makes its child partially transparent.
/// ///
/// This class paints its child into an intermediate buffer and then blends the /// This class paints its child into an intermediate buffer and then blends the
......
...@@ -1266,6 +1266,7 @@ class PhysicalShape extends SingleChildRenderObjectWidget { ...@@ -1266,6 +1266,7 @@ class PhysicalShape extends SingleChildRenderObjectWidget {
} }
} }
// POSITIONING AND SIZING NODES // POSITIONING AND SIZING NODES
/// A widget that applies a transformation before painting its child. /// A widget that applies a transformation before painting its child.
...@@ -3548,8 +3549,6 @@ class IntrinsicHeight extends SingleChildRenderObjectWidget { ...@@ -3548,8 +3549,6 @@ class IntrinsicHeight extends SingleChildRenderObjectWidget {
/// * The [catalog of layout widgets](https://flutter.dev/widgets/layout/). /// * The [catalog of layout widgets](https://flutter.dev/widgets/layout/).
class Baseline extends SingleChildRenderObjectWidget { class Baseline extends SingleChildRenderObjectWidget {
/// Creates a widget that positions its child according to the child's baseline. /// Creates a widget that positions its child according to the child's baseline.
///
/// The [baseline] and [baselineType] arguments must not be null.
const Baseline({ const Baseline({
super.key, super.key,
required this.baseline, required this.baseline,
...@@ -3577,6 +3576,25 @@ class Baseline extends SingleChildRenderObjectWidget { ...@@ -3577,6 +3576,25 @@ class Baseline extends SingleChildRenderObjectWidget {
} }
} }
/// A widget that causes the parent to ignore the [child] for the purposes
/// of baseline alignment.
///
/// See also:
///
/// * [Baseline], a widget that positions a child relative to a baseline.
class IgnoreBaseline extends SingleChildRenderObjectWidget {
/// Creates a widget that ignores the child for baseline alignment purposes.
const IgnoreBaseline({
super.key,
super.child,
});
@override
RenderIgnoreBaseline createRenderObject(BuildContext context) {
return RenderIgnoreBaseline();
}
}
// SLIVERS // SLIVERS
......
...@@ -52,4 +52,56 @@ void main() { ...@@ -52,4 +52,56 @@ void main() {
expect(childParentData.offset.dy, equals(10.0)); expect(childParentData.offset.dy, equals(10.0));
expect(parent.size, equals(const Size(100.0, 110.0))); expect(parent.size, equals(const Size(100.0, 110.0)));
}); });
test('RenderFlex and RenderIgnoreBaseline (control test -- with baseline)', () {
final RenderBox a, b;
final RenderBox root = RenderFlex(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: <RenderBox>[
a = RenderParagraph(
const TextSpan(text: 'a', style: TextStyle(fontSize: 128.0, fontFamily: 'FlutterTest')), // places baseline at y=96
textDirection: TextDirection.ltr,
),
b = RenderParagraph(
const TextSpan(text: 'b', style: TextStyle(fontSize: 32.0, fontFamily: 'FlutterTest')), // 24 above baseline, 8 below baseline
textDirection: TextDirection.ltr,
),
],
);
layout(root);
final Offset aPos = a.localToGlobal(Offset.zero);
final Offset bPos = b.localToGlobal(Offset.zero);
expect(aPos.dy, 0.0);
expect(bPos.dy, 96.0 - 24.0);
});
test('RenderFlex and RenderIgnoreBaseline (with ignored baseline)', () {
final RenderBox a, b;
final RenderBox root = RenderFlex(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: <RenderBox>[
RenderIgnoreBaseline(
child: a = RenderParagraph(
const TextSpan(text: 'a', style: TextStyle(fontSize: 128.0, fontFamily: 'FlutterTest')),
textDirection: TextDirection.ltr,
),
),
b = RenderParagraph(
const TextSpan(text: 'b', style: TextStyle(fontSize: 32.0, fontFamily: 'FlutterTest')),
textDirection: TextDirection.ltr,
),
],
);
layout(root);
final Offset aPos = a.localToGlobal(Offset.zero);
final Offset bPos = b.localToGlobal(Offset.zero);
expect(aPos.dy, 0.0);
expect(bPos.dy, 0.0);
});
} }
...@@ -1135,6 +1135,62 @@ void main() { ...@@ -1135,6 +1135,62 @@ void main() {
contains('verticalDirection: up'), contains('verticalDirection: up'),
])); ]));
}); });
testWidgets('Row and IgnoreBaseline (control -- with baseline)', (WidgetTester tester) async {
await tester.pumpWidget(
const Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: <Widget>[
Text(
'a',
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 128.0, fontFamily: 'FlutterTest'), // places baseline at y=96
),
Text(
'b',
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 32.0, fontFamily: 'FlutterTest'), // 24 above baseline, 8 below baseline
),
],
),
);
final Offset aPos = tester.getTopLeft(find.text('a'));
final Offset bPos = tester.getTopLeft(find.text('b'));
expect(aPos.dy, 0.0);
expect(bPos.dy, 96.0 - 24.0);
});
testWidgets('Row and IgnoreBaseline (with ignored baseline)', (WidgetTester tester) async {
await tester.pumpWidget(
const Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: <Widget>[
IgnoreBaseline(
child: Text(
'a',
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 128.0, fontFamily: 'FlutterTest'), // places baseline at y=96
),
),
Text(
'b',
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 32.0, fontFamily: 'FlutterTest'), // 24 above baseline, 8 below baseline
),
],
),
);
final Offset aPos = tester.getTopLeft(find.text('a'));
final Offset bPos = tester.getTopLeft(find.text('b'));
expect(aPos.dy, 0.0);
expect(bPos.dy, 0.0);
});
} }
HitsRenderBox hits(RenderBox renderBox) => HitsRenderBox(renderBox); HitsRenderBox hits(RenderBox renderBox) => HitsRenderBox(renderBox);
......
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