Skip to content

Instantly share code, notes, and snippets.

@aklehm
Created October 24, 2023 07:21
Show Gist options
  • Save aklehm/cd2eb6462f85f6fabd07e660bd5f0ce1 to your computer and use it in GitHub Desktop.
Save aklehm/cd2eb6462f85f6fabd07e660bd5f0ce1 to your computer and use it in GitHub Desktop.
Util to measure the size of a flutter widget before build.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
/// Small utility to measure a widget before actually putting it on screen.
///
/// This can be helpful e.g. for positioning context menus based on the size they will take up.
///
/// NOTE: Use sparingly, since this takes a complete layout and sizing pass for the subtree you
/// want to measure.
///
/// Compare https://api.flutter.dev/flutter/widgets/BuildOwner-class.html
/// Original code from https://stackoverflow.com/a/74701386/13869584
/// The measured widget must be a [Directionality] widget.
class MeasureUtil {
static Size measureWidget(Widget widget, [BoxConstraints constraints = const BoxConstraints()]) {
final PipelineOwner pipelineOwner = PipelineOwner();
final _MeasurementView rootView = pipelineOwner.rootNode = _MeasurementView(constraints);
final BuildOwner buildOwner = BuildOwner(focusManager: FocusManager());
final RenderObjectToWidgetElement<RenderBox> element = RenderObjectToWidgetAdapter<RenderBox>(
container: rootView,
debugShortDescription: '[root]',
child: widget,
).attachToRenderTree(buildOwner);
try {
rootView.scheduleInitialLayout();
pipelineOwner.flushLayout();
return rootView.size;
} finally {
// Clean up.
element.update(RenderObjectToWidgetAdapter<RenderBox>(container: rootView));
buildOwner.finalizeTree();
}
}
}
class _MeasurementView extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
final BoxConstraints boxConstraints;
_MeasurementView(this.boxConstraints);
@override
void performLayout() {
assert(child != null);
child!.layout(boxConstraints, parentUsesSize: true);
size = child!.size;
}
@override
void debugAssertDoesMeetConstraints() => true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment