我像这样在一行中有一个TextField和一个IconButton。
我希望仅在TextField中有文本时才启用IconButton。我正在使用provider package进行状态管理。
这是ChangeNotifier实现。
class ChatMessagesProvider with ChangeNotifier{
List<ChatMessage> chatMessages = <ChatMessage>[];
bool messageTyped = false;
ChatMessagesProvider(this.chatMessages);
void newMessage(String textMessage){
ChatMessage message = ChatMessage(textMessage);
this.chatMessages.add(message);
notifyListeners();
}
int messageCount() => chatMessages.length;
void updateMessageTyped(bool typed){
this.messageTyped = typed;
// notifyListeners(); Un-comennting this makes the Text disappear everytime I type something on the text field
}
}
这是实际的小部件:
class TextCompose extends StatelessWidget {
final TextEditingController _composeTextEditingController = new TextEditingController();
TextCompose(this.chatMessagesProvider);
final ChatMessagesProvider chatMessagesProvider;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Flexible(
child: new TextField(
controller: _composeTextEditingController,
onSubmitted: (String text) {
_onMessageSubmitted(text, context);
},
onChanged: (String text){
if(text.length > 0){
chatMessagesProvider.updateMessageTyped(true);
print(text);
}
else{
chatMessagesProvider.updateMessageTyped(false);
print("No text typed");
}
},
decoration: new InputDecoration.collapsed(
hintText: "Enter message"
),
),
),
new Container(
margin: new EdgeInsets.all(8.0),
child: new IconButton(
color: Theme.of(context).accentColor,
icon: new Icon(Icons.send),
disabledColor: Colors.grey,
onPressed:chatMessagesProvider.messageTyped // This dosen't work
? () => _onMessageSubmitted(_composeTextEditingController.text, context)
: null,
),
)
],
),
);
}
void _onMessageSubmitted(String text, BuildContext context){
if(chatMessagesProvider.messageTyped) { // This works fine.
// clear the message compose text box
_composeTextEditingController.clear();
// add the message to provider.
chatMessagesProvider.newMessage(text);
// set the message typed to false
chatMessagesProvider.messageTyped = false;
}
我正在使用来自ChatMessageProvider的messageTyped来检查TextField中是否有任何文本。当我在_onMessageSubmitted方法中检查它时,它似乎工作正常,但是当我在IconButton的onPressed属性中检查它的值时,它似乎工作正常。
我知道这是因为我在键入文本时可以看到IconButton保持禁用状态(颜色不会从灰色更改),而我可以按下虚拟键盘上的Submit按钮,并且可以从TextField中清除文本(按调用_composeTextEditingController.clear())
问题:
当从_onMessageSubmitted调用时,为什么chatMessagesProvider.messageTyped返回正确的值,但是从IconButton的onPrssed属性调用时,为什么不能返回正确的值?
我该如何在Flutter中调试类似的东西,我真的很想在onPressedAttribute中放置一个断点并查看chatMessagesProvider.messageTyped的值
让我知道您是否需要查看更多我的代码。
答案 0 :(得分:1)
onPressed:chatMessagesProvider.messageTyped
这行是在窗口小部件构建期间执行的,因此它始终是默认值,除非您使用notify listener
或有状态窗口小部件重建窗口小部件,否则它永远不会刷新。
将currently being typed message
存储在provider
中,并根据currently being typed message
是否为空来使发送按钮启用/禁用。
答案 1 :(得分:1)
您说您正在使用'provider_package',但实际上您的布局中没有Provider
。相反,您有一个没有侦听器的自定义构建ChangeNotifier
-您确实在调用notifyListeners()
,但实际上没有侦听器,因此不会触发任何重建。为了使按钮更改其onPressed
函数引用并隐式更改其颜色,需要进行重建。
对于调试,您可以在onPressed
行上设置一个断点,但是只有在重建过程中它才会被击中。
要理解的最重要的事情是,您对onPressed
的函数引用将被正确调用,但是需要重新构建才能使小部件在视觉上发生变化。
尽管您当前的ChangeNotifier
实现没有多大意义,但只需将对updateMessageTyped
的调用包装在setState
内就可以解决视觉问题-每次键入后,您的断点也会被击中/已删除的字符。
答案 2 :(得分:0)
最简单的解决方案是,首先可以使窗口小部件StatefulWidget
。
您需要在State
类中使用布尔值:
bool hasText = false;
然后创建initState
:
@override
void initState() {
_composeTextEditingController.addListener(() {
if (_composeTextEditingController.text.isNotEmpty) {
setState(() {
hasText = true;
});
} else {
setState(() {
hasText = false;
});
}
});
super.initState();
}
也不要忘记dispose
:
@override
void dispose() {
_composeTextEditingController.dispose();
super.dispose();
}
最后是您的build
方法:
Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _composeTextEditingController,
)),
if (hasText) IconButton(icon: Icon(Icons.send), onPressed: () {})
],
),