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

标签 dart flutter

我在父小部件中有一个底部导航,在子小部件中有一些文本字段。当用户单击导航选项卡并且其中一个文本字段为空时,它将把焦点设置在特定的文本字段上。

我正在使用从一位开发人员那里学到的构造函数方法,但是我无法让它工作。好像我没有正确传递上下文。我不确定。

谁能发现我的错误或建议可以达到相同结果的其他方法?

登录.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 ... flutter :FocusNode#419f4(FOCUSED) requestFocus...

但是文本框仍然没有焦点。

最佳答案

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

首页:

import 'package:flutter/material.dart';
import 'package:focus_node/widgets/MyInputWidget.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: 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,
         ),
        );
       }
      }

希望这对您有所帮助。

关于dart - Flutter - 如何将 focusNode 从 Parent 设置为 Child 小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55834900/

相关文章:

angular - AngularDart组件下拉列表选择selectionChange事件

flutter - 如何自动导入 FLUTTER 包 Visual Studio Code ver : 1. 51.1 Windows 10

flutter 形式 : Get the list of fields in error

firebase - 如果密码或用户电子邮件格式不正确,则返回错误消息

flutter - 推送通知上的Flutter Show App图标徽章

android - flutter 下拉对齐不正确

flutter - 如何在 IntelliJ Idea 中嵌套自动生成的 Dart 文件?

flutter - 如何在dart中将List <Class>插入Map <String,dynamic>中?

user-interface - flutter :将常规小部件放在CustomPaint Canvas 顶部

Flutter 推送通知应用程序背景 : firebase_messaging