使用GlobalKey在flutter中获取Widget的高度

16

我正在努力使用 GlobalKey 获取小部件的高度,但是在渲染布局后调用获取高度的函数以确保上下文可用时,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),),
    );
  }
}
3个回答

22

您需要在小部件构造函数中使用 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),
      ),
    );
  }
}

以上代码出现了以下错误 //错误:空对象上调用了getter 'context'。 - Asad Jamil
如果您尝试通过runApp(TestPage());运行它,它将返回此错误,但是如果您在TestPage中包装MediaQuery和Directionality小部件(提供数据和textDirection参数),或者使用MaterialApp或WidgetsApp小部件,它应该可以运行(至少对我来说是这样)。 - userManyNumbers
@AsadJamil,然而,在你的例子中,键不是常量。 - David Schneider
我得到了编译错误:类型'RenderObject'没有定义'size' getter。 - Cyrill

4

按以下方式定义构造函数:

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

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


0
有时更好的方法是使用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),
      ),
    );
  },
);

这种方法动态地提供信息,通常在动画中非常有用。


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