【问题标题】:Flutter sets textfield cursor to start when changing controller's textFlutter 在更改控制器的文本时将文本字段光标设置为启动
【发布时间】:2021-04-10 21:33:56
【问题描述】:

我有一个可重用的文本字段类,如下所示:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {
  String value = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: MyTextField(
            value: value,
            onChange: (val) {
              setState(() {
                value = val;
              });
            },
          ),
        ),
      ),
    );
  }
}

typedef ChangeCallback = void Function(String value);

class MyTextField extends StatefulWidget {
  final ChangeCallback onChange;
  final String value;

  const MyTextField({this.onChange = _myDefaultFunc, this.value = ""});
  
  static _myDefaultFunc(String value){}

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

class _MyTextFieldState extends State<MyTextField> {
  final controller = TextEditingController();

  @override
  void initState() {
    controller.text = widget.value;
    super.initState();
  }

  @override
  void didUpdateWidget(covariant MyTextField oldWidget) {
    controller.text = widget.value;
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
      onChanged: (value) {
        widget.onChange(value);
      },
    );
  }
}

如您所见,如果值发生更改,则调用onChange 回调,并且该值再次发送回TextField。这个问题是每次我更新值时,TextField 总是将光标设置为开始。可能是因为更新的值每次都被发送回TextField?不确定。你能帮我解决这个问题吗?

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    不要使用onChanged 方法来获取文本字段的值,而是传递一个TextEditingController。

    class MyTextField extends StatefulWidget {
      final TextEditingController controller;
      final String defaultValue;
    
      const MyTextField({@required this.controller, this.defaultValue = ''});
    
      @override
      _MyTextFieldState createState() => _MyTextFieldState();
    }
    
    class _MyTextFieldState extends State<MyTextField> {
      @override
      void initState() {
        widget.controller.text = widget.defaultValue;
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return TextField(
          controller: widget.controller,
        );
      }
    }
    

    这样,您可以在父小部件中声明 TextEditingController 以获取值,就像您通常使用 Flutter 的原生 TextFormField 一样。

    【讨论】:

      【解决方案2】:

      无需更新 didUpdateWidget 中的值

      //@override
      //   void didUpdateWidget(covariant MyTextField oldWidget) {
      //     controller.text = widget.value;
      //     super.didUpdateWidget(oldWidget);
      //   }
      

      我刚刚注释掉了这个函数,代码工作正常 以下是完整代码

      import 'package:flutter/material.dart';
      
      void main() {
        runApp(MyApp());
      }
      
      class MyApp extends StatefulWidget {
        @override
        _MyAppState createState() => _MyAppState();
      }
      
      class _MyAppState extends State<MyApp> {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Flutter Demo',
            home: MyHomePage(),
          );
        }
      }
      
      class MyHomePage extends StatefulWidget {
        @override
        _MyHomePageState createState() => _MyHomePageState();
      }
      
      class _MyHomePageState extends State<MyHomePage> {
        String value = "";
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: SafeArea(
              child: Column(children: [
                SizedBox(height:50),
                Text("text input: $value"),
                SizedBox(height:50),
                Center(
                  child: MyTextField(
                    value: value,
                    onChange: (val) {
                      setState(() {
                        value = val;
                      });
                    },
                  ),
                ),
              ]),
            ),
          );
        }
      }
      
      typedef ChangeCallback = void Function(String value);
      
      class MyTextField extends StatefulWidget {
        final ChangeCallback onChange;
        final String value;
      
        const MyTextField({this.onChange = _myDefaultFunc, this.value = ""});
      
        static _myDefaultFunc(String value) {}
      
        @override
        _MyTextFieldState createState() => _MyTextFieldState();
      }
      
      class _MyTextFieldState extends State<MyTextField> {
        final controller = TextEditingController();
      
        @override
        void initState() {
          controller.text = widget.value;
          super.initState();
        }
      
      //   @override
      //   void didUpdateWidget(covariant MyTextField oldWidget) {
      //     controller.text = widget.value;
      //     super.didUpdateWidget(oldWidget);
      //   }
      
        @override
        Widget build(BuildContext context) {
          return TextField(
            controller: controller,
            onChanged: (value) {
              widget.onChange(value);
            },
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-31
        • 1970-01-01
        • 2022-11-19
        • 1970-01-01
        • 2011-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多