StatefulWidget中的布局更改后,“'_ listenerAttached':不正确”

时间:2018-10-10 12:02:24

标签: flutter

我正在尝试根据某些TextFormField的焦点状态来更改Flutter屏幕的布局。

我在处理以下代码方面遇到麻烦:

  • 当我聚焦触发布局更改的文本字段之一时,键盘处于隐藏状态。
  • 聚焦其他文本字段时,出现错误:
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 :(得分:2)

似乎需要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;
      }
    });
  }
}