«_listenerAttached»: не соответствует действительности после изменения макета в StatefulWidget - PullRequest
0 голосов
/ 10 октября 2018

Я пытаюсь изменить расположение экрана флаттера, основываясь на состоянии фокусировки некоторого TextFormField.

У меня проблема со следующим фрагментом кода:

  • Клавиатура прячется, когда я фокусирую одно из текстовых полей, которое вызывает изменение макета.
  • При фокусировке другого текстового поля я получаю сообщение об ошибке:
The following assertion was thrown building _ScrollableScope:
'package:flutter/src/rendering/editable.dart': Failed assertion: line 590 pos 14: 
'_listenerAttached': is not true.

Чего мне здесь не хватает?

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: MyHomePage(),
        ));
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isCollapsed;

  FocusNode _focusOne = FocusNode();
  FocusNode _focusTwo = FocusNode();

  TextEditingController _controllerOne = TextEditingController();
  TextEditingController _controllerTwo = TextEditingController();

  @override
  void initState() {
    super.initState();
    _isCollapsed = false;

    _focusOne.addListener(_onFocusChange);
    _focusTwo.addListener(_onFocusChange);
  }

  @override
  Widget build(BuildContext context) {
    if (!_isCollapsed) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text("Title"),
            TextFormField(
              focusNode: _focusOne,
              controller: _controllerOne,
            ),
            TextFormField(focusNode: _focusTwo, controller: _controllerTwo)
          ],
        ),
      );
    } else {
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          TextFormField(
            focusNode: _focusOne,
            controller: _controllerOne,
          ),
          TextFormField(focusNode: _focusTwo, controller: _controllerTwo)
        ],
      );
    }
  }

  void _onFocusChange() {
    setState(() {
      if (_focusOne.hasFocus || _focusTwo.hasFocus) {
        _isCollapsed = true;
      } else {
        _isCollapsed = false;
      }
    });
  }
}

1 Ответ

0 голосов
/ 23 октября 2018

Кажется, что поле key необходимо для отслеживания TextFormField между изменениями макета.
Вот рабочее решение:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: MyHomePage(),
        ));
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isCollapsed;

  FocusNode _focusOne = FocusNode();
  FocusNode _focusTwo = FocusNode();

  TextEditingController _controllerOne = TextEditingController();
  TextEditingController _controllerTwo = TextEditingController();

  final GlobalKey<FormState> _formKeyOne = GlobalKey<FormState>();
  final GlobalKey<FormState> _formKeyTwo = GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    _isCollapsed = false;

    _focusOne.addListener(_onFocusChange);
    _focusTwo.addListener(_onFocusChange);
  }

  @override
  Widget build(BuildContext context) {
    if (!_isCollapsed) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text("Title"),
            TextFormField(
              key: _formKeyOne,
              focusNode: _focusOne,
              controller: _controllerOne,
            ),
            TextFormField(
              key: _formKeyTwo,
              focusNode: _focusTwo, 
            controller: _controllerTwo)
          ],
        ),
      );
    } else {
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          TextFormField(
            key: _formKeyOne,
            focusNode: _focusOne,
            controller: _controllerOne,
          ),
          TextFormField(
            key: _formKeyTwo,
            focusNode: _focusTwo, 
          controller: _controllerTwo)
        ],
      );
    }
  }

  void _onFocusChange() {
    setState(() {
      if (_focusOne.hasFocus || _focusTwo.hasFocus) {
        _isCollapsed = true;
      } else {
        _isCollapsed = false;
      }
    });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...