选择下拉按钮时,TextField 焦点卡住
Posted
技术标签:
【中文标题】选择下拉按钮时,TextField 焦点卡住【英文标题】:TextField focus stuck when dropdown button is selected 【发布时间】:2020-02-19 03:40:45 【问题描述】:我有一个文本字段和一个下拉菜单,它们都由 Bloc 控制。我遇到的问题是,一旦选择了文本字段,如果用户随后尝试从下拉菜单中选择某些内容,它就不会放弃焦点。菜单出现,然后立即消失,焦点仍然在文本字段上。
这是一个演示问题的基本应用程序:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Textfield Focus Example',
home: HomePage(),
);
class HomePage extends StatelessWidget
FormBloc formBloc = FormBloc();
final List<DropdownMenuItem> userMenuItems = ['Bob', 'Frank']
.map((String name) => DropdownMenuItem(
value: name,
child: Text(name),
))
.toList();
@override
Widget build(BuildContext context)
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// user - drop down menu
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('To: '),
StreamBuilder<String>(
stream: formBloc.selectedUser,
builder: (context, snapshot)
return DropdownButton(
items: userMenuItems,
value: snapshot.data,
onChanged: formBloc.selectUser);
),
],
),
// amount - text field
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Amount: '),
Container(
width: 100.0,
child: StreamBuilder<double>(
stream: formBloc.billAmount,
builder: (context, snapshot)
return TextField(
keyboardType: TextInputType.number,
onChanged: formBloc.newBillAmount,
);
)),
],
),
],
),
),
);
class FormBloc
StreamController<String> _selectedUserController = StreamController<String>();
Stream<String> get selectedUser =>
_selectedUserController.stream;
Function get selectUser => _selectedUserController.sink.add;
//Amount
StreamController<double> _billAmountController = StreamController<double>();
Stream<double> get billAmount =>
_billAmountController.stream;
void newBillAmount(String amt) =>
_billAmountController.sink.add(double.parse(amt));
void dispose()
_selectedUserController.close();
_billAmountController.close();
我是否需要手动为 textField 声明 FocusNode 并告诉它何时放弃焦点?还是有其他原因导致文本字段占据了所有注意力?
【问题讨论】:
【参考方案1】:将这行代码添加到您的 TextField:focusNode: FocusNode(canRequestFocus: false)
。
这应该可以防止您的TextField
在单击下拉列表后请求焦点。
代码:
// amount - text field
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Amount: '),
Container(
width: 100.0,
child: StreamBuilder<double>(
stream: formBloc.billAmount,
builder: (context, snapshot)
return TextField(
focusNode: FocusNode(canRequestFocus: false)
keyboardType: TextInputType.number,
onChanged: formBloc.newBillAmount,
);
)),
],
)
【讨论】:
您也可以尝试在 TextField 中使用 autofocus: false。【参考方案2】:抱歉,您需要在 DropDownButton Widget 的 onTapListener 中添加以下代码。当您在下拉菜单中选择或点击屏幕外时,它将移除对文本字段的关注。谢谢
FocusScope.of(context).requestFocus(new FocusNode());
【讨论】:
【参考方案3】:此问题已解决并合并到flutter主频道https://github.com/flutter/flutter/pull/42482
这解决了我们目前无法在 同一页面,因为当下拉菜单获得焦点时键盘消失会导致指标更改,并且下拉菜单在激活时会立即消失。
【讨论】:
【参考方案4】:上面的答案只有在你不想调用 requestFocus() 方法的情况下才是正确的。但在我的情况下,它是一个聊天应用程序,我希望文本字段在消息被滑动时获得焦点。如果设置布尔参数canRequestFocus,则为false。那我就不行了。
在 chatPage 应用栏中,我使用了一个弹出菜单,这导致了同样的问题(无意中集中注意力。)
所以,对我有用的是,在 popupmenu 的 onSelected(String str) 方法的最顶部,我调用了这个语句:
messageFocusNode.nextFocus(); //messageFocusNode is the focusNode of the TextField.
虽然我不知道为什么以及如何,但这对我有用。我是新手,如果您知道原因,请更新我的答案。
【讨论】:
以上是关于选择下拉按钮时,TextField 焦点卡住的主要内容,如果未能解决你的问题,请参考以下文章
如何在按钮单击时在 SwiftUI 中为 TextField 设置文本
当textfield为空时禁用按钮等待其他文本字段中的任何更改
NativeScript Vue - 将焦点放在 TextField 上