【发布时间】:2026-01-03 00:10:02
【问题描述】:
我遇到了一个非常奇怪的 Flutter bug,也许有人对此有所了解。
Flutter 目前还没有很好的方法来自动从表单中的 TextField 移动到 Textfield。推荐的解决方案是为每个 Textfield 创建一个 FocusNode,然后当用户完成编辑时,以编程方式选择下一个 FocusNode。
似乎工作正常,但是如果您的表单不在应用程序的第一条路线上,它也会导致一些非常奇怪的视觉故障(通常情况并非如此)
在第二条路线上,当你点击一个 TextField 时,装饰会瞬间闪烁然后消失,但光标会保留。您可以继续选择 TextFields,最终您将在每个字段上都有一个光标。该字段仍然正常运行,因此这纯粹是视觉故障。
TextField with more than one curser
问题似乎与导航器密切相关。如果您使用自定义 FocusNodes 在第一条路线上创建一个屏幕,它的行为很好。相反,如果您不在第二个屏幕上使用 FocusNodes,它也可以。只有当您将这两者结合起来时才会出现问题。
这是一个出现此问题的简单应用程序。
import 'package:flutter/material.dart';
void main() {
runApp(TestApp());
}
class TestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: TestScreen(),
);
}
}
class TestScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: RaisedButton(
onPressed: () => _pushSecondScreen(context),
child: Text('Push to a new screen')
),
),
)
);
}
void _pushSecondScreen(BuildContext context) {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => SecondTest()));
}
}
class SecondTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: ListView(
padding: EdgeInsets.all(20.0),
children: List<Widget>.generate(10, (i) => _buildTextField(i)),
),
);
}
Widget _buildTextField(int index) {
// The custom focus node is thrown in here for example, but in a real world app,
// a reference to the node would be kept so the app can manage focus between the nodes
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: TextField(
focusNode: FocusNode(),
decoration: InputDecoration(
labelText: 'Field $index',
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0))
)
),
),
);
}
}
我发布了代码以在此要点中复制此问题: https://gist.github.com/bkayfitz-cara/8da2afd964c7f4417435e9df49b4cd9e
【问题讨论】:
-
This article 可能会有所帮助,尤其是关于在构建方法之外进行初始化的部分。
标签: flutter