在Flutter中,我如何为Stateless widget定义基线?

4

“Baseline”小部件难道不是已经为您做到了这一点吗? - Rémi Rousselet
1个回答

7
如果您想定义一个基线,无法直接在无状态小部件中完成。您需要在其对应的RenderBox中进行操作,并实现computeDistanceToActualBaseline()方法。
请查看ListTile实现此处。您将看到_RenderListTile RenderBox实现了上述方法,返回标题小部件的基线。
  @override
  double computeDistanceToActualBaseline(TextBaseline baseline) {
    assert(title != null);
    final BoxParentData parentData = title.parentData;
    return parentData.offset.dy + title.getDistanceToActualBaseline(baseline);
  }

在这种情况下,标题的基线是文本小部件的底部。
所有这些都是必需的,因为 Baseline 小部件尝试获取子小部件的基线。如果您不使用上述方法提供明确的基线,则它将仅使用其底部位置。
您可以在下面找到一个 BaselineBox 的示例,其中您可以从顶部设置任意基线。
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));
  }
}

理想情况下,我可以有一个 AddBaseline 小部件,我可以像这样使用它:widget = AddBaseline(baseline:15.0, child: wiget); - MarcG
我已经编辑了答案,并添加了一个BaselineBox的实现。 - chemamolins
@MarcG 初始化这个 final bool fromBottom; - Blasanka
完美运行。感谢你的出色回答! - MarcG
不错的工作 @chemamolins,我还没有尝试过。但是看起来很好,负基线呢?应该是可能的吧。你限制它为>= 0.0有特别的原因吗? - Simon
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接