英文:
How to reset list to original state in Flutter VSCODE
问题
以下是代码部分的中文翻译:
import 'package:flutter/material.dart';
List<String> items = ["CGS 1540", "COP 2512", "COP 2513", "CIS 3213",
"CGS 3303", "CIS 3363", "COP 3515", "CEN 3722", "CGS 3853", "CNT 4104",
"CNT 4403", "COP 4538", "CNT 4603", "CIS 4935", "COP 4703"];
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<StatefulWidget> {
List<String> initialData = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
initialData.addAll(items);
}
@override
Widget build(BuildContext context) {
const title = '课程列表';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.symmetric(vertical:16),
prototypeItem: ListTile(
title: Text(items.first),
),
itemBuilder: (context, index) {
return Dismissible(
background: Container(
child: Text('删除 ${items[index]}',
style: TextStyle(color: Colors.white),
),
color: Colors.red,
),
secondaryBackground:Container(
child: Text('归档 ${items[index]}',
style: TextStyle(color: Colors.white),
),
alignment: Alignment.centerRight,
color: Colors.yellow,
),
key: ValueKey<String>(items[index]),
onDismissed: (DismissDirection direction){
if(direction == DismissDirection.startToEnd) {
setState(() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(
SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem 已删除'),
action: SnackBarAction(
label: '撤销',
onPressed: (){
setState(() => items.insert(index, deletedItem));
},
),
)
);
},
)
else if (direction == DismissDirection.endToStart){
setState(() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(
SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem 已归档'),
action: SnackBarAction(
label: '撤销',
onPressed: (){
setState(() => items.insert(index, deletedItem));
},
),
)
);
},
}
},
child: ListTile(
title: Text(
'${items[index]}',
)
)
);
},
),
floatingActionButton: FloatingActionButton(
onPressed:(){
setState(() {
initialData.clear();
fillInitialData();
});
},
tooltip: '重置',
child: const Icon(Icons.autorenew),
),
),
);
}
}
如果您需要进一步的帮助,请告诉我。
英文:
I've been messing around with the information I have found online, but haven't been able to make my code work, please help.
I need my list to be able to restore to its original content.
Here is my code so far:
import 'package:flutter/material.dart';
List<String> items = ["CGS 1540", "COP 2512", "COP 2513", "CIS 3213",
"CGS 3303", "CIS 3363", "COP 3515", "CEN 3722", "CGS 3853", "CNT 4104",
"CNT 4403", "COP 4538", "CNT 4603", "CIS 4935", "COP 4703" ];
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<StatefulWidget> {
List<String>initialData = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
initialData.addAll(items);
}
@override
Widget build(BuildContext context) {
const title = 'Course List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.symmetric(vertical:16),
prototypeItem: ListTile(
title: Text(items.first),
),
itemBuilder: (context, index) {
return Dismissible(
background: Container(
child: Text('Delete ${items[index]}',
style: TextStyle(color: Colors.white),
),
color: Colors.red,
),
secondaryBackground:Container(
child: Text('Archive ${items[index]}',
style: TextStyle(color: Colors.white),
),
alignment: Alignment.centerRight,
color: Colors.yellow,
),
key: ValueKey<String>(items[index]),
onDismissed: (DismissDirection direction){
if(direction == DismissDirection.startToEnd) {
setState(() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(
SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem deleted'),
action: SnackBarAction(
label: 'Undo',
onPressed: (){
setState(() => items.insert(index, deletedItem));
},
),
)
);
},
);
}
else if (direction == DismissDirection.endToStart){
setState(() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(
SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem Archived'),
action: SnackBarAction(
label: 'Undo',
onPressed: (){
setState(() => items.insert(index, deletedItem));
},
),
)
);
},
);
}
},
child: ListTile(
title: Text(
'${items[index]}',
)
)
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: (){
setState(() {
initialData.clear();
fillInitialData();
});
},
tooltip: 'Reset',
child: const Icon(Icons.autorenew),
),
),
);
}
}
I've looked through many posts I've seen on here, but they have either been with slider or numbers so I am stuck, please just help me figure out how to use the action button to reset the list to its original state before any deletions are archiving was done.
答案1
得分: 0
以下是代码部分的翻译:
所以基本上要注意的一件事是,`items.remove` 实际上修改了**原始列表**,这意味着当你从列表`items`中移除元素时,被移除的元素将不再存在。
对于你当前的代码,一个*快速修复*是,因为你已经在`initialData`中制作了项目的副本,所以只需清除项目并重新添加它们到`items`列表,因为这是你的小部件状态所依赖的。
```dart
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
items.clear();
items.addAll(initialData);
initialData.clear();
fillInitialData();
});
},
tooltip: '重置',
child: const Icon(Icons.autorenew),
),
但是如果你有兴趣,这段代码可以更加简洁,以下是如何做的(我会尽量解释得尽可能详细)
有几个可以改进的地方:
- 你的状态不应该依赖于全局变量,而是可以将
items
列表传递给你的有状态小部件。 - 状态对象应该负责处理状态,也就是说无论你做什么...
以下是我对你的代码所做的更改
首先,我将items
列表更改为字符串的常量列表,它将用作单一真相来源。
const List<String> items = [
"CGS 1540",
"COP 2512",
"COP 2513",
"CIS 3213",
"CGS 3303",
"CIS 3363",
"COP 3515",
"CEN 3722",
"CGS 3853",
"CNT 4104",
"CNT 4403",
"COP 4538",
"CNT 4603",
"CIS 4935",
"COP 4703"
];
其次,我在有状态小部件中添加了一个最终列表属性,并使状态类扩展了State<MyStatefulWidget>
,以便我们可以在状态对象中使用该属性。
class MyStatefulWidget extends StatefulWidget {
final List<String> items;
const MyStatefulWidget({super.key, required this.items});
@override
MyStatefulWidgetState createState() => MyStatefulWidgetState();
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
...
}
现在,无论你对状态做什么都不会影响你的原始小部件,这样你可以将相同的小部件用于不同的列表。因此,我在状态类中添加了一个字符串列表属性,它将用于状态,因此每当需要更新状态时,应该修改该列表。
现在可以执行类似于这样的操作
List<String> items = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
items.clear();
items.addAll(widget.items);
}
...
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
fillInitialData();
});
},
tooltip: '重置',
child: const Icon(Icons.autorenew),
),
最后,这是修改后的完整代码
完整代码
import 'package:flutter/material.dart';
const List<String> items = [
"CGS 1540",
"COP 2512",
"COP 2513",
"CIS 3213",
"CGS 3303",
"CIS 3363",
"COP 3515",
"CEN 3722",
"CGS 3853",
"CNT 4104",
"CNT 4403",
"COP 4538",
"CNT 4603",
"CIS 4935",
"COP 4703"
];
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: MyStatefulWidget(
items: items,
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
final List<String> items;
const MyStatefulWidget({super.key, required this.items});
@override
MyStatefulWidgetState createState() => MyStatefulWidgetState();
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
List<String> items = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
items.clear();
items.addAll(widget.items);
}
@override
Widget build(BuildContext context) {
const title = '课程列表';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.symmetric(vertical: 16),
prototypeItem: ListTile(
title: Text(items.first),
),
itemBuilder: (context, index) {
return Dismissible(
background: Container(
color: Colors.red,
child: Text(
'删除 ${items[index]}',
style: const TextStyle(color: Colors.white),
),
),
secondaryBackground: Container(
alignment: Alignment.centerRight,
color: Colors.yellow,
child: Text(
'存档 ${items[index]}',
style: const TextStyle(color: Colors.white),
),
),
key: ValueKey<String>(items[index]),
onDismissed: (DismissDirection direction) {
if (direction == DismissDirection.startToEnd) {
setState(
() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem 已删除'),
action: SnackBarAction(
label: '撤销',
onPressed: () {
setState(
() => items.insert(index, deletedItem));
},
),
));
},
);
} else if (direction == DismissDirection.endToStart) {
setState(
() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem 已存档'),
action: SnackBarAction(
label:
<details>
<summary>英文:</summary>
So essentially one thing to look out for is that `items.remove` actually modifies the **original list**, meaning that when you remove elements from the list `items`, the removed element will no longer be there.
A *quick fix* to your current code is, since you've already made a copy of the items in `initialData`, is just to clear the items and re-add them to the `items` list since that is what the state of your widget *depends on*
```dart
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
items.clear();
items.addAll(initialData);
initialData.clear();
fillInitialData();
});
},
tooltip: 'Reset',
child: const Icon(Icons.autorenew),
),
but this code could be much cleaner and here is how if you are interested (ill try to explain as much as I can)
there are several things that could be improved:
- your state should not be depending on a global variable and instead you can pass the
items
list to your stateful widget - the state object should be the one handling, well... the state, meaning that what ever your
here are the changes I have done to your code to clean it up
firstly, I made the items
list a constant list of strings and it will be used as a single source of truth
const List<String> items = [
"CGS 1540",
"COP 2512",
"COP 2513",
"CIS 3213",
"CGS 3303",
"CIS 3363",
"COP 3515",
"CEN 3722",
"CGS 3853",
"CNT 4104",
"CNT 4403",
"COP 4538",
"CNT 4603",
"CIS 4935",
"COP 4703"
];
secondly, I added a final list attribute to the stateful widget and made the state class extend State<MyStatefulWidget>
so that we could use that attribute in the state object.
class MyStatefulWidget extends StatefulWidget {
final List<String> items;
const MyStatefulWidget({super.key, required this.items});
@override
MyStatefulWidgetState createState() => MyStatefulWidgetState();
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
...
}
now what ever you do to your state will not affect your original widget, and this way you could reuse the same widget for different lists. So that being said, I added a List of string attribute in the state class that will be used for the state so whenever the state needs to be updated, that list should be modified.
So something like this can now be done
List<String> items = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
items.clear();
items.addAll(widget.items);
}
....
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
fillInitialData();
});
},
tooltip: 'Reset',
child: const Icon(Icons.autorenew),
),
finally, here is the modified full code
full code
import 'package:flutter/material.dart';
const List<String> items = [
"CGS 1540",
"COP 2512",
"COP 2513",
"CIS 3213",
"CGS 3303",
"CIS 3363",
"COP 3515",
"CEN 3722",
"CGS 3853",
"CNT 4104",
"CNT 4403",
"COP 4538",
"CNT 4603",
"CIS 4935",
"COP 4703"
];
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: MyStatefulWidget(
items: items,
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
final List<String> items;
const MyStatefulWidget({super.key, required this.items});
@override
MyStatefulWidgetState createState() => MyStatefulWidgetState();
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
List<String> items = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
items.clear();
items.addAll(widget.items);
}
@override
Widget build(BuildContext context) {
const title = 'Course List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.symmetric(vertical: 16),
prototypeItem: ListTile(
title: Text(items.first),
),
itemBuilder: (context, index) {
return Dismissible(
background: Container(
color: Colors.red,
child: Text(
'Delete ${items[index]}',
style: const TextStyle(color: Colors.white),
),
),
secondaryBackground: Container(
alignment: Alignment.centerRight,
color: Colors.yellow,
child: Text(
'Archive ${items[index]}',
style: const TextStyle(color: Colors.white),
),
),
key: ValueKey<String>(items[index]),
onDismissed: (DismissDirection direction) {
if (direction == DismissDirection.startToEnd) {
setState(
() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem deleted'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
setState(
() => items.insert(index, deletedItem));
},
),
));
},
);
} else if (direction == DismissDirection.endToStart) {
setState(
() {
String deletedItem = items.removeAt(index);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(
duration: const Duration(
seconds: 2,
),
content: Text('$deletedItem Archived'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
setState(
() => items.insert(index, deletedItem));
},
),
));
},
);
}
},
child: ListTile(
title: Text(
items[index],
)));
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
fillInitialData();
});
},
tooltip: 'Reset',
child: const Icon(Icons.autorenew),
),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论