Created
October 24, 2023 07:21
-
-
Save aklehm/cd2eb6462f85f6fabd07e660bd5f0ce1 to your computer and use it in GitHub Desktop.
Util to measure the size of a flutter widget before build.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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