Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Flutter, how can I define a baseline for a Stateless widget?

I have created a stateless widget, and I want to define a baseline for it, so that I can use it with the Baseline widget (https://docs.flutter.io/flutter/widgets/Baseline-class.html).

How can I do that?

like image 361
MarcG Avatar asked Mar 06 '23 22:03

MarcG


1 Answers

If you want to define a baseline you can't do it directly in the stateless widget. You need to mess around its corresponding RenderBox that needs to implement the computeDistanceToActualBaseline() method.

Give a look to the ListTile implementation here. You will see that the _RenderListTile RenderBox implements the above method returning the baseline of the title widget.

  @override
  double computeDistanceToActualBaseline(TextBaseline baseline) {
    assert(title != null);
    final BoxParentData parentData = title.parentData;
    return parentData.offset.dy + title.getDistanceToActualBaseline(baseline);
  }

In this case, the baseline of the title is the bottom of the Text widget.

All this is needed because the Baseline widget tries to get the baseline of the child widget. If you don't provide a explicit baseline with the above method, it just uses its bottom position.

You can find below an example of a BaselineBox where you can set an arbitrary baseline from top.

import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

class BaselineBox extends SingleChildRenderObjectWidget {
  const BaselineBox({Key key, @required this.baseline, Widget child})
      : assert(baseline != null),
        super(key: key, child: child);

  final double baseline;

  @override
  RenderBaselineBox createRenderObject(BuildContext context) =>
      new RenderBaselineBox(baseline: baseline);

  @override
  void updateRenderObject(
      BuildContext context, RenderBaselineBox renderObject) {
    renderObject.baseline = baseline;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(new DoubleProperty('baseline', baseline));
  }
}

class RenderBaselineBox extends RenderProxyBox {
  RenderBaselineBox({
    RenderBox child,
    @required double baseline,
  })  : assert(baseline != null),
        assert(baseline >= 0.0),
        assert(baseline.isFinite),
        _baseline = baseline,
        super(child);

  double get baseline => _baseline;
  double _baseline;

  set baseline(double value) {
    assert(value != null);
    assert(value >= 0.0);
    assert(value.isFinite);
    if (_baseline == value) return;
    _baseline = value;
    markNeedsLayout();
  }

  @override
  double computeDistanceToActualBaseline(TextBaseline baselineType) {
    return _baseline;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(new DoubleProperty('baseline', baseline));
  }
}
like image 50
chemamolins Avatar answered Mar 19 '23 06:03

chemamolins