TextEditingController使小部件失去以前的状态

时间:2019-01-01 14:31:08

标签: android ios dart flutter

当我在TextEditingController中使用CupertinoTextField并切换到另一个小部件(页面)并返回时,该页面中的先前状态会丢失。

取消评论//controller: textController,时一切正常。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test',
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
            body: TabBarView(
              children: [new Search(), new Setting(),
              ],
            ),
            bottomNavigationBar: Container(
              height: 60,
              child: new TabBar(
                tabs: [
                  Tab(icon: new Icon(Icons.search)),
                  Tab(icon: new Icon(Icons.settings)),
                ],
                labelColor: Colors.blue,
                unselectedLabelColor: Colors.grey,
              ),
            )
        ),
      ),
    );
  }
}

class Setting extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return IconButton(
        icon: Icon(Icons.check),
        onPressed: () {
          Navigator.push(context, CupertinoPageRoute(
              builder: (context) =>
              new Scaffold(
                appBar: AppBar(title: Text('3'),),
              )));
        });
  }

}

class Search extends StatefulWidget {
  @override
  createState() => new SearchState();
}

class SearchState extends State<Search> {

  String currentWord = '';
  final TextEditingController textController = new TextEditingController();

  @override
  void dispose() {
    textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Row(
            children: <Widget>[
              new Expanded(
                child: new CupertinoTextField(
                  style: TextStyle(color: Colors.white),
                  cursorColor: Colors.white,
                  //controller: textController,
                  maxLines: 1,
                  clearButtonMode: OverlayVisibilityMode.editing,
                  onChanged: (text) {
                    setState(() {
                      currentWord = text;
                    });
                  },
                ),
              ),
            ],
          ),
        ),
        body: ListView.builder(
            itemCount: 5,
            itemBuilder: (context, i) {
              return Text(currentWord);
            })
    );
  }

}

预期结果(未设置控制器):取回并且状态保持不变。

expected

实际结果(在设置了控制器的情况下):返回并丢失状态

actual

1 个答案:

答案 0 :(得分:2)

对观察到的行为的解释如下:

CupertinoTextField使用内部TextEditingController,框架会为此内部元素自动设置AutomaticKeepAlive。该keepAlive负责保持状态。

如果您使用自己的控制器,则因为该框架无法为您完成附加AutomaticKeepAlive

以下代码段将keepAlive添加到您的代码中:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test',
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
            body: TabBarView(
              children: [
                new Search(),
                new Setting(),
              ],
            ),
            bottomNavigationBar: Container(
              height: 60,
              child: new TabBar(
                tabs: [
                  Tab(icon: new Icon(Icons.search)),
                  Tab(icon: new Icon(Icons.settings)),
                ],
                labelColor: Colors.blue,
                unselectedLabelColor: Colors.grey,
              ),
            )),
      ),
    );
  }
}

class Setting extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return IconButton(
        icon: Icon(Icons.check),
        onPressed: () {
          Navigator.push(
              context,
              CupertinoPageRoute(
                  builder: (context) => new Scaffold(
                        appBar: AppBar(
                          title: Text('3'),
                        ),
                      )));
        });
  }
}

class Search extends StatefulWidget {
  @override
  createState() => new SearchState();
}

class SearchState extends State<Search> with AutomaticKeepAliveClientMixin {
  String currentWord = '';
  final TextEditingController textController = new TextEditingController();

  @override
  void initState() {
    super.initState();
    textController?.addListener(updateKeepAlive);
  }

  @override
  void dispose() {
    textController?.removeListener(updateKeepAlive);
    textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context); // See AutomaticKeepAliveClientMixin.
    return new Scaffold(
        appBar: new AppBar(
          title: new Row(
            children: <Widget>[
              new Expanded(
                child: new CupertinoTextField(
                  style: TextStyle(color: Colors.white),
                  cursorColor: Colors.white,
                  controller: textController,
                  maxLines: 1,
                  clearButtonMode: OverlayVisibilityMode.editing,
                  onChanged: (text) {
                    setState(() {
                      currentWord = text;
                    });
                  },
                ),
              ),
            ],
          ),
        ),
        body: ListView.builder(
            itemCount: 5,
            itemBuilder: (context, i) {
              return Text(currentWord);
            }));
  }

  @override
  bool get wantKeepAlive => textController?.text?.isNotEmpty == true;
}