Unverified Commit ecb468f3 authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Baseline Aligned Row (#30746)

Text in a baseline aligned row now works, and the height of the row is properly calculated.
parent 3bbb8d8b
......@@ -1058,8 +1058,7 @@ class _RenderDecoration extends RenderBox {
@override
double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(false, 'not implemented');
return 0.0;
return _boxParentData(input).offset.dy + input.computeDistanceToActualBaseline(baseline);
}
// Records where the label was painted.
......
......@@ -508,7 +508,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
// Intrinsic cross size is the max of the intrinsic cross sizes of the
// children, after the flexible children are fit into the available space,
// with the children sized using their max intrinsic dimensions.
// TODO(ianh): Support baseline alignment.
// Get inflexible space using the max intrinsic dimensions of fixed children in the main direction.
final double availableMainSpace = extent;
......@@ -750,6 +749,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
if (totalFlex > 0 || crossAxisAlignment == CrossAxisAlignment.baseline) {
final double spacePerFlex = canFlex && totalFlex > 0 ? (freeSpace / totalFlex) : double.nan;
child = firstChild;
double maxSizeAboveBaseline = 0;
double maxSizeBelowBaseline = 0;
while (child != null) {
final int flex = _getFlex(child);
if (flex > 0) {
......@@ -809,8 +810,18 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
return true;
}());
final double distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
if (distance != null)
if (distance != null) {
maxBaselineDistance = math.max(maxBaselineDistance, distance);
maxSizeAboveBaseline = math.max(
distance,
maxSizeAboveBaseline,
);
maxSizeBelowBaseline = math.max(
child.size.height - distance,
maxSizeBelowBaseline,
);
crossSize = maxSizeAboveBaseline + maxSizeBelowBaseline;
}
}
final FlexParentData childParentData = child.parentData;
child = childParentData.nextSibling;
......
......@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
......@@ -146,6 +148,64 @@ void main() {
});
});
group('Row', () {
testWidgets('multiple baseline aligned children', (WidgetTester tester) async {
final UniqueKey key1 = UniqueKey();
final UniqueKey key2 = UniqueKey();
const double fontSize1 = 54;
const double fontSize2 = 14;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text('big text',
key: key1,
style: const TextStyle(fontSize: fontSize1),
),
Text('one\ntwo\nthree\nfour\nfive\nsix\nseven',
key: key2,
style: const TextStyle(fontSize: fontSize2)
),
],
),
),
),
),
);
final RenderBox textBox1 = tester.renderObject(find.byKey(key1));
final RenderBox textBox2 = tester.renderObject(find.byKey(key2));
final RenderBox rowBox = tester.renderObject(find.byType(Row));
// The two Texts are baseline aligned, so some portion of them extends
// both above and below the baseline. The first has a huge font size, so
// it extends higher above the baseline than usual. The second has many
// lines, but being aligned by the first line's baseline, they hang far
// below the baseline. The size of the parent row is just enough to
// contain both of them.
const double ahemBaselineLocation = 0.8; // https://web-platform-tests.org/writing-tests/ahem.html
const double aboveBaseline1 = fontSize1 * ahemBaselineLocation;
const double belowBaseline1 = fontSize1 * (1 - ahemBaselineLocation);
const double aboveBaseline2 = fontSize2 * ahemBaselineLocation;
const double belowBaseline2 = fontSize2 * (1 - ahemBaselineLocation) + fontSize2 * 6;
final double aboveBaseline = math.max(aboveBaseline1, aboveBaseline2);
final double belowBaseline = math.max(belowBaseline1, belowBaseline2);
expect(rowBox.size.height, greaterThan(textBox1.size.height));
expect(rowBox.size.height, greaterThan(textBox2.size.height));
expect(rowBox.size.height, closeTo(aboveBaseline + belowBaseline, .001));
expect(tester.getTopLeft(find.byKey(key1)).dy, 0);
expect(
tester.getTopLeft(find.byKey(key2)).dy,
closeTo(aboveBaseline1 - aboveBaseline2, .001),
);
});
});
test('UnconstrainedBox toString', () {
expect(
const UnconstrainedBox(constrainedAxis: Axis.vertical,).toString(),
......
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