ключ контейнера «исчезает» при попытке получить его размер

#flutter #layout #key

#flutter #макет #Клавиша

Вопрос:

Я пытаюсь получить размер контейнера с помощью функции, которая обычно работает. Теперь он терпит неудачу в соответствии с отладчиком, потому что он не может найти ключ контейнера в дереве виджетов. Ошибка заключается в том, что метод ‘findRenderObject’ был вызван в null. Получатель: null Я вижу ключ, getSize() но при переходе в строку с ошибкой я нахожу объяснение, что он не может найти виджет, если возвращается значение null. Есть идеи, почему это так?

 import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
 @override
  _MyWidgetState createState() => _MyWidgetState();
}


class _MyWidgetState extends State<MyWidget>  {
  GlobalKey _keyScreenContainer = GlobalKey(); // <-------- key declared
   @override
  Widget build(BuildContext context) {
    return SafeArea(
          child: Container(
            key: _keyScreenContainer,         // <--------- key allocated
            width: 20, height: 20,
            child: Text("${getSize(_keyScreenContainer, context)}"),
            )
      );
  }
  
  Size getSize(GlobalKey _key, BuildContext context) {
    final RenderBox renderBox = _key.currentContext.findRenderObject(); // <---- error
    final boxSize = renderBox.size;
    print (boxSize);
    return boxSize;
  }
}
  

Комментарии:

1. Я не уверен, но можете ли вы попробовать свой ключ без подчеркивания (_): keyScreenContainer и getSize(ключ GlobalKey, …

Ответ №1:

Ошибка заключается в том, что вы вызываете функцию getSize еще до завершения сборки. Вы можете вызвать функцию после завершения компоновки виджета либо в initState с помощью WidgetsBinding.instance .addPostFrameCallback((_) => someFunction()), либо с помощью чего-то вроде кнопки. Пожалуйста, смотрите код ниже :

 import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
 @override
  _MyWidgetState createState() => _MyWidgetState();
}


class _MyWidgetState extends State<MyWidget>  {
  GlobalKey _keyScreenContainer = GlobalKey();
  
  @override
  void initState(){
    
            super.initState();
    
    WidgetsBinding.instance
        .addPostFrameCallback((_) => print("${getSize(_keyScreenContainer, context)}"));
    
  }
   @override
  Widget build(BuildContext context) {
    return Column(children: [
          Container(
            key: _keyScreenContainer,     
            width: 20, height: 20,
            child: Text("abc"),
      ), RaisedButton(onPressed:(){
            print("${getSize(_keyScreenContainer, context)}");
            
            
          },child:Text("Get size"))]);
  }
  
  Size getSize(GlobalKey key, BuildContext context) {
    final RenderBox renderBox = key.currentContext.findRenderObject(); // <---- error
    final boxSize = renderBox.size;
    print (boxSize);
    return boxSize;
  }
}
  

Комментарии:

1. Это, безусловно, имеет смысл. Мне было интересно, почему getSize работает на другой странице, но теперь, снова взглянув на нее, я понимаю, что она вызывается там только после нажатия кнопки. Приветствия!