如何获得小部件的高度?

我不明白如何LayoutBuilder用于获取小部件的高度。

我需要显示小部件列表并获取它们的高度,以便可以计算一些特殊的滚动效果。我正在开发一个程序包,其他开发人员提供了小部件(我不控制它们)。我读过LayoutBuilder可以用来获取高度。

在非常简单的情况下,我尝试将Widget包装在LayoutBuilder.builder中并将其放入堆栈中,但是我总是得到minHeight

0.0maxHeightINFINITY。我在滥用LayoutBuilder吗?

:似乎LayoutBuilder是行不通的。我发现CustomSingleChildLayout几乎是一个解决方案。

我扩展了该委托,并且能够在getPositionForChild(Size size, Size

childSize)方法中获得小部件的高度。但是,第一个被调用的方法是Size getSize(BoxConstraints

constraints)并且作为约束,我将0赋给INFINITY,因为我将这些CustomSingleChildLayouts放置在ListView中。

我的问题是SingleChildLayoutDelegate的getSize运行就像需要返回视图的高度一样。我当时不知道孩子的身高。我只能返回constraints.smallest(为0,高度为0),或者返回constraints.biggest,它为无穷大并导致应用崩溃。

在文档中甚至说:

…但是父母的大小不能取决于孩子的大小。

这是一个怪异的限制。

回答:

要获取屏幕上小部件的大小/位置,可以使用GlobalKey使其获取BuildContext然后找到该RenderBox特定小部件的,其中将包含其全局位置和渲染的大小。

只需注意一件事:如果未呈现小部件,则该上下文可能不存在。ListView仅当窗口小部件可能可见时才渲染它们,这可能会导致问题。

另一个问题是,由于尚未渲染小部件,因此您RenderBoxbuild通话期间无法获得小部件的。


但是在构建期间我需要大小! 我能做什么?

有一个很酷的小部件可以帮助您:Overlay及其及其OverlayEntry。它们用于在其他所有内容(类似于堆栈)的顶部显示小部件。

但最酷的是,它们的build流向不同。它们是 常规小部件 之后 构建的。

这具有一种超酷的含义:OverlayEntry可以具有取决于实际窗口小部件树的窗口小部件的大小。


好的。 但是,OverlayEntry不需要手动重建吗?

是的,他们有。但是还有另一件事要注意:ScrollController传递给Scrollable,与相似,是可收听的AnimationController

这意味着您可以将AnimatedBuilder和组合使用ScrollController,这将具有在滚动条上自动重建窗口小部件的可爱效果。非常适合这种情况,对吗?


将所有内容组合为示例:

在下面的示例中,您将看到一个覆盖,该覆盖在其内部的小部件之后ListView并具有相同的高度。

import 'package:flutter/material.dart';

import 'package:flutter/scheduler.dart';

class MyHomePage extends StatefulWidget {

const MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override

_MyHomePageState createState() => _MyHomePageState();

}

class _MyHomePageState extends State<MyHomePage> {

final controller = ScrollController();

OverlayEntry sticky;

GlobalKey stickyKey = GlobalKey();

@override

void initState() {

if (sticky != null) {

sticky.remove();

}

sticky = OverlayEntry(

builder: (context) => stickyBuilder(context),

);

SchedulerBinding.instance.addPostFrameCallback((_) {

Overlay.of(context).insert(sticky);

});

super.initState();

}

@override

void dispose() {

sticky.remove();

super.dispose();

}

@override

Widget build(BuildContext context) {

return Scaffold(

body: ListView.builder(

controller: controller,

itemBuilder: (context, index) {

if (index == 6) {

return Container(

key: stickyKey,

height: 100.0,

color: Colors.green,

child: const Text("I'm fat"),

);

}

return ListTile(

title: Text(

'Hello $index',

style: const TextStyle(color: Colors.white),

),

);

},

),

);

}

Widget stickyBuilder(BuildContext context) {

return AnimatedBuilder(

animation: controller,

builder: (_,Widget child) {

final keyContext = stickyKey.currentContext;

if (keyContext != null) {

// widget is visible

final box = keyContext.findRenderObject() as RenderBox;

final pos = box.localToGlobal(Offset.zero);

return Positioned(

top: pos.dy + box.size.height,

left: 50.0,

right: 50.0,

height: box.size.height,

child: Material(

child: Container(

alignment: Alignment.center,

color: Colors.purple,

child: const Text("^ Nah I think you're okay"),

),

),

);

}

return Container();

},

);

}

}

导航到其他屏幕时,后续通话将保持可见。

sticky.remove();

以上是 如何获得小部件的高度? 的全部内容, 来源链接: utcz.com/qa/398964.html

回到顶部