在颤动中使用其 GlobalKey 获取 Widget 的高度

Posted

技术标签:

【中文标题】在颤动中使用其 GlobalKey 获取 Widget 的高度【英文标题】:get height of a Widget using its GlobalKey in flutter 【发布时间】:2018-10-11 10:17:09 【问题描述】:

我正在努力使用其 GlobalKey 获取 Widget 的高度。 在渲染布局后调用获取高度的函数以确保上下文可用,但 key.currentState 和 key.currentContext 仍然返回 null。

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget
  @override
  State<StatefulWidget> createState() => new TestPageState();


class TestPageState extends State<TestPage>
  final TestWidget testWidget = new TestWidget();

  @override
  initState() 
    //calling the getHeight Function after the Layout is Rendered
    WidgetsBinding.instance
        .addPostFrameCallback((_) => getHeight());

    super.initState();
  

  void getHeight()
    final GlobalKey key = testWidget.key;

    //returns null:
    final State state = key.currentState;
    //returns null:
    final BuildContext context = key.currentContext;

    //Error: The getter 'context' was called on null.
    final RenderBox box = state.context.findRenderObject();

    print(box.size.height);
    print(context.size.height);
  

  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      body: testWidget,
    );
  


class TestWidget extends StatefulWidget
  @override
  Key get key => new GlobalKey<TestWidgetState>();

  @override
  State<StatefulWidget> createState() => new TestWidgetState();


class TestWidgetState extends State<TestWidget>
  @override
  Widget build(BuildContext context) 
    return new Container(
      child: new Text("Test", style: const TextStyle(fontSize: 32.0, fontWeight: FontWeight.bold),),
    );
  

【问题讨论】:

【参考方案1】:

您需要在小部件构造函数中使用super 将该键分配给小部件。不要将其添加为字段。 Key 也必须是常量。

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget 
  @override
  State<StatefulWidget> createState() => new TestPageState();


class TestPageState extends State<TestPage> 
  final key = new GlobalKey<TestWidgetState>();

  @override
  initState() 
    //calling the getHeight Function after the Layout is Rendered
    WidgetsBinding.instance.addPostFrameCallback((_) => getHeight());

    super.initState();
  

  void getHeight() 
    //returns null:
    final State state = key.currentState;
    //returns null:
    final BuildContext context = key.currentContext;

    //Error: The getter 'context' was called on null.
    final RenderBox box = state.context.findRenderObject();

    print(box.size.height);
    print(context.size.height);
  

  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      body: new TestWidget(key: key),
    );
  


class TestWidget extends StatefulWidget 
  TestWidget(Key key) : super(key: key);

  @override
  State<StatefulWidget> createState() => new TestWidgetState();


class TestWidgetState extends State<TestWidget> 
  @override
  Widget build(BuildContext context) 
    return new Container(
      child: new Text(
        "Test",
        style: const TextStyle(fontSize: 32.0, fontWeight: FontWeight.bold),
      ),
    );
  

【讨论】:

上面的代码给出了这个错误 //Error: The getter 'context' was called on null. @AsadJamil 如果您尝试通过runApp(TestPage()); 运行它,它将返回此错误,但如果您将 TestPage 包装在 MediaQuery 和 Directionality 小部件(提供数据和 textDirection 参数)或 MaterialApp 或WidgetsApp 小部件,它应该可以运行(或者至少对我有用)。 @AsadJamil 但是,在您的示例中,密钥不是恒定的。【参考方案2】:

像这样定义你的构造函数:

const MyWidget(GlobalKey key) : super(key:key);.

框架将BuildContextState 对象存储在Widget.key 字段中,该字段由构造函数而不是任意key 字段传递给对象。

【讨论】:

【参考方案3】:

有时更好的方法是使用 LayoutBuilder。在这种情况下,代码看起来像

return LayoutBuilder(
  builder: (context, constraints) 
    print('Available container sizes - $constraints.maxWidth - $constraints.maxHeight');
    return Container(
      child: new Text(
        "Test",
        style: const TextStyle(fontSize: 32.0, fontWeight: FontWeight.bold),
      ),
    );
  ,
);

这种方法动态地提供信息,通常对动画很有用。

【讨论】:

以上是关于在颤动中使用其 GlobalKey 获取 Widget 的高度的主要内容,如果未能解决你的问题,请参考以下文章

如何获取TextFormField的高度

flutter通过GlobalKey在自定义Widget外部获取其state刷新页面

颤动中的不同导航栏

如何在颤动中取消焦点文本字段?

flutter通过 GlobalKey 获取界面任意元素坐标尺寸

Flutter中GlobalKey的用法