Flutter-如何将focusNode从Parent设置为Child小部件?

时间:2019-04-24 16:42:38

标签: dart flutter

我在父窗口小部件中有一个底部导航,在子窗口小部件中有一些文本字段。当用户单击导航选项卡,并且其中一个文本字段为空时,它将专注于特定的文本字段。

我正在使用从一名开发人员那里学到的构造方法,但是无法正常工作。似乎我没有正确地传递上下文。我不确定。

有人能够发现我的错误或建议其他方法来达到相同的结果吗?

login.dart

class Login extends StatefulWidget{

  @override
  State<StatefulWidget> createState() {
    return _LoginState();
  }
}

class _LoginState extends State<Login> {

  FocusNode focusNode;
  Page1 focus;

  @override
  void initState() {
    super.initState();
    focusNode = new FocusNode();
    focus = new Page1(focusNode: focusNode);
  }

  int currentBottomNavIndex = 0;

  List<Widget> bottomNav = [
    Page1(),
    Page2(),
  ];

  onTapped(int index) {

    //if(textfield not empty) {
      //setState(() {
      //currentBottomNavIndex = index;
      //});
    //}else {
      focus.setFocus(context);
    //}
  }

  @override
  Widget build(BuildContext context){

          return new Scaffold(
            appBar: new AppBar(
              title: Text('Login Page'),
            ),

            body: bottomNav[currentBottomNavIndex],

            bottomNavigationBar: BottomNavigationBar(
              onTap: onTapped,
              //onTap: requestFocus(context),
              currentIndex: currentBottomNavIndex,
              type: BottomNavigationBarType.fixed,
              items: [
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  title: Text("Page1"),
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.mail),
                  title: Text('Page2'),
                ),
              ],
            ),
          );
  }
}

page1.dart

class Page1 extends StatefulWidget {

  final FocusNode focusNode;

  const Page1({Key key, this.focusNode}) : super(key: key);

  void setFocus(BuildContext context) {
    print("$focusNode requestFocus...");
    FocusScope.of(context).requestFocus(focusNode);
  }

  @override
  State<StatefulWidget> createState() {
    return _Page1State();
  }
}

class _Page1State extends State<Page1> {

  TextEditingController name1 = TextEditingController();

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {


    return new Scaffold(

        body: SingleChildScrollView(
            child: Column(

              children: <Widget>[
                nameApp(),
              ],
            )
        )
    );

  }

  Widget nameApp(){
    return Container(

        margin: EdgeInsets.all(50.0),
        //width: 185,
        child: Center(

            child: Row(

                children: [

                  Container(
                    child: Text("Name :", style: TextStyle(fontSize: 15), ),
                  ),

                  Container(

                    child: Flexible(

                      child: TextField(

                        focusNode: widget.focusNode,
                        controller: name1,
                        onTap: (){
                          name1.clear();
                        },
                        onChanged: (String str){

                        },
                        textAlign: TextAlign.center,
                        decoration: InputDecoration(
                          contentPadding: EdgeInsets.symmetric(vertical: 5),
                          hintText: "Full Name",
                          hintStyle: TextStyle(fontSize: 14),
                        ),
                      ),
                    ),
                  ),
                ]

            )
        )

    );
  }
}

当用户单击底部的选项卡时,我希望文本字段处于焦点,但是什么也没发生。

我注意到子窗口小部件中的方法已被调用:

flutter:FocusNode#419f4 requestFocus ... 扑扑:FocusNode#419f4(FOCUSED)requestFocus ...

但是文本字段仍然不是焦点。

1 个答案:

答案 0 :(得分:0)

我为此创建了一个简单的示例项目,它对我的​​工作很好。 请查看我的解决方案:

主页:

  import 'package:flutter/material.dart';
  import 'package:focus_node/widgets/MyInputWidget.dartvoid 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: MyHomePage(title: 'Flutter Demo Home Page'),
    );
   }
 }

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

   final String title;

   @override
   _MyHomePageState createState() => _MyHomePageState();
 }

class _MyHomePageState extends State<MyHomePage> {

 FocusNode field1FocusNode = FocusNode(); //Create first FocusNode
 FocusNode field2FocusNode = FocusNode(); //Create second FocusNode

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(

    title: Text(widget.title),
  ),
  body: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 35),
          child: MyInputWidget(
            focusNode: field1FocusNode, //Provide the first FocusNode in the constructor
            hint: "Email",
            onEditCompleted: (){
              FocusScope.of(context).requestFocus(field2FocusNode); //Request focus
            },
          ),
        ),
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 35),
          child: MyInputWidget(
            focusNode: field2FocusNode, //Provide the second FocusNode 
            hint: "Password",
            onEditCompleted: (){
              FocusScope.of(context).requestFocus(field1FocusNode); //Request focus
            },
          ),
        )
      ],
    ),
   ),
  );
 }
}

“自定义小部件”需要重点关注:

class MyInputWidget extends StatefulWidget {
  final FocusNode focusNode;
  final String hint;
  final VoidCallback onEditCompleted;

  MyInputWidget({this.focusNode, this.hint, this.onEditCompleted});

  @override
  _MyInputWidgetState createState() => _MyInputWidgetState();
 }

 class _MyInputWidgetState extends State<MyInputWidget> {
    @override
    Widget build(BuildContext context) {
      return Container(
            padding: EdgeInsets.all(8),
            child: TextField(
            focusNode: widget.focusNode, //The FocusNode provided by the parent widget
            decoration: InputDecoration(
            hintText: widget.hint
           ),
          onEditingComplete: widget.onEditCompleted,
         ),
        );
       }
      }

希望这会有所帮助。