10000 Baseline alignment breaks intrinsic height · Issue #65895 · flutter/flutter · GitHub
[go: up one dir, main page]

Skip to content
Baseline alignment breaks intrinsic height #65895
Closed
@tvolkert

Description

@tvolkert

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:

boxes

... 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:

boxes

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: layoutSystemChrome and Framework's Layout Issuesfound in release: 1.22Found to occur in 1.22frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0