mirror of
https://github.com/flutter/flutter.git
synced 2026-02-14 23:02:04 +08:00
Baseline Aligned Row (#30746)
Text in a baseline aligned row now works, and the height of the row is properly calculated.
This commit is contained in:
parent
3bbb8d8b77
commit
ecb468f335
@ -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(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user