Closed
Description
Steps to reproduce
Run the following app:
import 'package:flutter/widgets.dart';
void main() {
runApp(BugReport());
}
class BugReport extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
ColoredBox(
color: Color(0xffffffff),
child: Row(
textDirection: TextDirection.ltr,
crossAxisAlignment: CrossAxisAlignment.baseline,
children: [
BoxedBaseline(width: 50, height: 50, baseline: 25),
BoxedBaseline(width: 100, height: 100, baseline: 10),
BoxedBaseline(width: 100, height: 100, baseline: 90),
],
),
),
],
);
}
}
class BoxedBaseline extends LeafRenderObjectWidget {
const BoxedBaseline({this.width, this.height, this.baseline});
final double width;
final double height;
final double baseline;
@override
RenderObject createRenderObject(BuildContext context) {
return RenderBoxedBaseline(
width: width,
height: height,
baseline: baseline,
);
}
@override
void updateRenderObject(BuildContext context, RenderBoxedBaseline renderObject) {
renderObject
..width = width
..height = height
..baseline = baseline;
}
}
class RenderBoxedBaseline extends RenderBox {
RenderBoxedBaseline({
double width,
double height,
double baseline,
}) {
this.width = width;
this.height = height;
this.baseline = baseline;
}
double _width;
double get width => _width;
set width(double value) {
_width = value;
markNeedsLayout();
}
double _height;
double get height => _height;
set height(double value) {
_height = value;
markNeedsLayout();
}
double _baseline;
double get baseline => _baseline;
set baseline(double value) {
_baseline = value;
markNeedsLayout();
}
@override
double computeMinIntrinsicWidth(double height) => width;
@override
double computeMaxIntrinsicWidth(double height) => width;
@override
double computeMinIntrinsicHeight(double width) => height;
@override
double computeMaxIntrinsicHeight(double width) => height;
@override
double computeDistanceToActualBaseline(TextBaseline _) => baseline;
@override
bool get sizedByParent => true;
@override
void performResize() {
size = constraints.constrainDimensions(width, height);
}
@override
void paint(PaintingContext context, Offset offset) {
Paint paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 1
..color = Color(0xff000000);
Rect rect = offset & size;
context.canvas.drawRect(rect.deflate(0.5), paint);
paint.color = Color(0xffff0000);
context.canvas.drawLine(
offset + Offset(0, baseline),
offset + Offset(size.width, baseline),
paint,
);
}
}
That app produces the following, correctly:
... then apply the following change to the app:
@@ -11,6 +11,7 @@ class BugReport extends StatelessWidget {
children: [
ColoredBox(
color: Color(0xffffffff),
+ child: IntrinsicHeight(
child: Row(
textDirection: TextDirection.ltr,
crossAxisAlignment: CrossAxisAlignment.baseline,
@@ -21,6 +22,7 @@ class BugReport extends StatelessWidget {
],
),
),
+ ),
],
);
}
... and refresh the app.
Expected behavior
You expect the same behavior as before you added the IntrinsicHeight
wrapper.
Actual behavior
The Row
reports its intrinsic height incorrectly, 'causing the app to look like this:
Diagnosis
RenderBox.computeDistanceToActualBaseline()
only works post-layout. There's currently no way in the framework for a RenderBox
to say "if I were size S, then my baseline would be B". Thus, when the Row
is asked for its intrinsic height, which is affected by the would-be baselines of its children, it has no way of knowing their would-be baselines.
Flutter version
[✓] Flutter (Channel master, 1.22.0-10.0.pre.153, on Mac OS X 10.15.3 19D76, locale en-US)
• Flutter version 1.22.0-10.0.pre.153 at /Users/tvolkert/project/flutter/flutter
• Framework revision 2e643651a9 (4 days ago), 2020-09-11 23:07:03 -0400
• Engine revision 16b900b63e
• Dart version 2.10.0 (build 2.10.0-117.0.dev)