Flutter:Dismissible 小部件内的 SnackBar 无法正常工作
Flutter: SnackBar inside Dismissible widget is not working properly
我的主屏幕是 Scaffold
,在其 body 处有 Dismissible
个小部件列表。每个 Dismissible
的 child 是我创建的自定义小部件,名为 Box
。我有一个 FloatingActionButton
将我带到一个新屏幕,我可以在其中添加更多 Box
到列表中。 (每个 Box
接收一个字符串作为参数,用作其标题)。
我希望方法 onDismissed
显示带有文本“(框的标题)已排除”的 SnackBar
。但是,这没有按预期工作。问题是它总是显示包含的最后一个框的标题,而不是我刚刚忽略的那个框的标题。例如,如果我添加一个名为“Box 1”的 Box
,然后添加一个名为“Box 2”的 Box
,然后我关闭“Box 1”,小吃店将显示“Box 2 excluded ".
我做错了什么?
相关代码如下:
import 'package:flutter/material.dart';
import 'box.dart';
import 'addCounter.dart';
class Home extends StatefulWidget {
@override
HomeState createState() => HomeState();
}
class HomeState extends State<Home> {
List<String> lista;
void incrementLista(String novoItem) {
print('$lista');
setState(() {
lista.add(novoItem);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counters'),
backgroundColor: Colors.black,
),
body: ListView.builder(
itemCount: lista.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(color: Colors.grey[800], child: Icon(Icons.delete, color: Colors.grey[100])),
key: Key(lista[index]),
onDismissed: (direction) {
setState(() {
lista.removeAt(index);
});
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(lista[index] + ' excluded.')));
},
child: Box(lista[index]));
},
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.grey[1000],
onPressed: () {
//Navega para tela de adicionar tarefa
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddCounter(f: incrementLista)));
},
child: Icon(Icons.add, color: Colors.white)),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomNavigationBar(
//backgroundColor: Colors.grey[50],
unselectedItemColor: Colors.grey[700],
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.list),
title: Text('List'),
),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('Chart'),
),
],
// currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
//onTap: _onItemTapped,
),
);
}
}
这里是 addCounter.dart 的代码:
import 'package:flutter/material.dart';
class AddCounter extends StatefulWidget {
final Function f;
AddCounter({@required this.f});
@override
_AddCounterState createState() => _AddCounterState();
}
class _AddCounterState extends State<AddCounter> {
final myController = TextEditingController();
@override
void dispose() {
myController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add a counter'),
backgroundColor: Colors.blue,
),
body: Column(children: [
Padding(
padding: EdgeInsets.all(15),
child: TextField(
controller: myController,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2)),
hintText: 'Type a name for the counter'),
),
),
RaisedButton(
color: Colors.green,
onPressed: () {
widget.f(myController.text);
Navigator.pop(context);
},
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
)
]));
}
}
我认为问题在于您首先删除了列表中的项目。当您显示 SnackBar 时,该项目已被删除,因此您无法在列表中访问它。所以我建议先显示 Snackbar,然后删除该项目。
像这样:(在你的itemBuilder
)
return Dismissible(
background: Container(color: Colors.grey[800], child: Icon(Icons.delete,
color: Colors.grey[100])),
key: Key(lista[index]),
onDismissed: (direction) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(lista[index] + ' excluded.')));
setState(() {
lista.removeAt(index);
});
},
child: Box(lista[index]));
},
我的主屏幕是 Scaffold
,在其 body 处有 Dismissible
个小部件列表。每个 Dismissible
的 child 是我创建的自定义小部件,名为 Box
。我有一个 FloatingActionButton
将我带到一个新屏幕,我可以在其中添加更多 Box
到列表中。 (每个 Box
接收一个字符串作为参数,用作其标题)。
我希望方法 onDismissed
显示带有文本“(框的标题)已排除”的 SnackBar
。但是,这没有按预期工作。问题是它总是显示包含的最后一个框的标题,而不是我刚刚忽略的那个框的标题。例如,如果我添加一个名为“Box 1”的 Box
,然后添加一个名为“Box 2”的 Box
,然后我关闭“Box 1”,小吃店将显示“Box 2 excluded ".
我做错了什么?
相关代码如下:
import 'package:flutter/material.dart';
import 'box.dart';
import 'addCounter.dart';
class Home extends StatefulWidget {
@override
HomeState createState() => HomeState();
}
class HomeState extends State<Home> {
List<String> lista;
void incrementLista(String novoItem) {
print('$lista');
setState(() {
lista.add(novoItem);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counters'),
backgroundColor: Colors.black,
),
body: ListView.builder(
itemCount: lista.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(color: Colors.grey[800], child: Icon(Icons.delete, color: Colors.grey[100])),
key: Key(lista[index]),
onDismissed: (direction) {
setState(() {
lista.removeAt(index);
});
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(lista[index] + ' excluded.')));
},
child: Box(lista[index]));
},
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.grey[1000],
onPressed: () {
//Navega para tela de adicionar tarefa
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddCounter(f: incrementLista)));
},
child: Icon(Icons.add, color: Colors.white)),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomNavigationBar(
//backgroundColor: Colors.grey[50],
unselectedItemColor: Colors.grey[700],
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.list),
title: Text('List'),
),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('Chart'),
),
],
// currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
//onTap: _onItemTapped,
),
);
}
}
这里是 addCounter.dart 的代码:
import 'package:flutter/material.dart';
class AddCounter extends StatefulWidget {
final Function f;
AddCounter({@required this.f});
@override
_AddCounterState createState() => _AddCounterState();
}
class _AddCounterState extends State<AddCounter> {
final myController = TextEditingController();
@override
void dispose() {
myController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add a counter'),
backgroundColor: Colors.blue,
),
body: Column(children: [
Padding(
padding: EdgeInsets.all(15),
child: TextField(
controller: myController,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2)),
hintText: 'Type a name for the counter'),
),
),
RaisedButton(
color: Colors.green,
onPressed: () {
widget.f(myController.text);
Navigator.pop(context);
},
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
)
]));
}
}
我认为问题在于您首先删除了列表中的项目。当您显示 SnackBar 时,该项目已被删除,因此您无法在列表中访问它。所以我建议先显示 Snackbar,然后删除该项目。
像这样:(在你的itemBuilder
)
return Dismissible(
background: Container(color: Colors.grey[800], child: Icon(Icons.delete,
color: Colors.grey[100])),
key: Key(lista[index]),
onDismissed: (direction) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(lista[index] + ' excluded.')));
setState(() {
lista.removeAt(index);
});
},
child: Box(lista[index]));
},