Flutter Dismissible Widget 关闭后重新显示小部件
Flutter Dismissible Widget re shows the widget after dismissing
我正在尝试制作一个列表,其中的图块在拖动时可以被删除,所以我使用了 Dismissible 小部件并且一切都按我想要的方式工作,但是当拖动图块以将其关闭时,图块会重新显示一些瞬间消失,这个 video
中显示了我的意思的演示
FutureBuilder(
future: getMyFavData(),
builder: (context, snapshot) {
if (snapshot.data == null)
return Container(
child: Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
)));
else
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var monthOfProductList =
snapshot.data.elementAt(index)['date'].toDate().month;
var monthNow = DateTime.now().month;
bool newItem = false;
if (monthNow - monthOfProductList == 0) {
newItem = true;
}
return Dismissible(
key: UniqueKey(),
onDismissed: (direction) async {
if (direction == DismissDirection.startToEnd) {
await deleteFromDataBase(
snapshot.data.elementAt(index).documentID);
setState(() {
snapshot.data.remove(index);
});
}
},
background: Container(
color: Colors.red,
child: Row(
children: [
Icon(
Icons.delete_forever,
color: Colors.white,
size: 100,
),
],
),
),
direction: DismissDirection.startToEnd,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductFullScreenView(
productInfo: snapshot.data.elementAt(index),
)));
},
child: ProductListCardVerticalFavorite(),
),
);
});
});
我不确定问题出在哪里,任何帮助将不胜感激
您使用 FutureBuilder
获取数据列表并在 onDismissed
上将其删除。
当您关闭一个项目时,保存它的小部件将再次重建,因此您无需调用 setState
。
此外,当您调用删除函数 (deleteFromDataBase
) 时,这将删除一些实际保存的数据,因此您无需将其从您获取的数据中删除,因为此处删除项目时会调用一个函数也将被调用以从实际保存的数据中删除它并且小部件将被重建并且另一个调用(getMyFavData()
)将在保存的数据上发生以获取它们但是这次结果是所有前一个没有删除的项目.
我用你的代码做了一个简单的例子,并做了一个假的未来调用:
import 'package:flutter/material.dart';
void main() {
runApp(Home());
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<String> lst = [
'1',
'2',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
];
Future<List<String>> getMyFavData() async {
return Future.value(lst);
}
Future<void> deleteFromDataBase(int index) async {
Future.delayed(Duration(milliseconds: 500)).then((_) {
lst.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: getMyFavData(),
builder: (context, snapshot) {
if (snapshot.data == null)
return Container(
child: Center(
child:
CircularProgressIndicator(backgroundColor: Colors.red),
),
);
else
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Dismissible(
key: UniqueKey(),
onDismissed: (direction) async {
if (direction == DismissDirection.startToEnd) {
await deleteFromDataBase(index);
}
},
background: Container(
color: Colors.red,
alignment: Alignment.centerLeft,
child: Icon(
Icons.delete_forever,
color: Colors.white,
),
),
direction: DismissDirection.startToEnd,
child: Container(
width: MediaQuery.of(context).size.width,
child: Text(lst[index]),
color: Colors.blue,
margin: EdgeInsets.all(5.0),
));
});
}),
),
);
}
}
您应该避免在构建方法中分配未来。在 initState 中保存一个实例,因为每次构建树时都会重新构建 future。
Future myCachedFuture;
@override
void initState() {
super.initState();
myCachedFuture = getMyFavData();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(future: myCachedFuture,)
}
我正在尝试制作一个列表,其中的图块在拖动时可以被删除,所以我使用了 Dismissible 小部件并且一切都按我想要的方式工作,但是当拖动图块以将其关闭时,图块会重新显示一些瞬间消失,这个 video
中显示了我的意思的演示FutureBuilder(
future: getMyFavData(),
builder: (context, snapshot) {
if (snapshot.data == null)
return Container(
child: Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
)));
else
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var monthOfProductList =
snapshot.data.elementAt(index)['date'].toDate().month;
var monthNow = DateTime.now().month;
bool newItem = false;
if (monthNow - monthOfProductList == 0) {
newItem = true;
}
return Dismissible(
key: UniqueKey(),
onDismissed: (direction) async {
if (direction == DismissDirection.startToEnd) {
await deleteFromDataBase(
snapshot.data.elementAt(index).documentID);
setState(() {
snapshot.data.remove(index);
});
}
},
background: Container(
color: Colors.red,
child: Row(
children: [
Icon(
Icons.delete_forever,
color: Colors.white,
size: 100,
),
],
),
),
direction: DismissDirection.startToEnd,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductFullScreenView(
productInfo: snapshot.data.elementAt(index),
)));
},
child: ProductListCardVerticalFavorite(),
),
);
});
});
我不确定问题出在哪里,任何帮助将不胜感激
您使用 FutureBuilder
获取数据列表并在 onDismissed
上将其删除。
当您关闭一个项目时,保存它的小部件将再次重建,因此您无需调用 setState
。
此外,当您调用删除函数 (deleteFromDataBase
) 时,这将删除一些实际保存的数据,因此您无需将其从您获取的数据中删除,因为此处删除项目时会调用一个函数也将被调用以从实际保存的数据中删除它并且小部件将被重建并且另一个调用(getMyFavData()
)将在保存的数据上发生以获取它们但是这次结果是所有前一个没有删除的项目.
我用你的代码做了一个简单的例子,并做了一个假的未来调用:
import 'package:flutter/material.dart';
void main() {
runApp(Home());
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<String> lst = [
'1',
'2',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
];
Future<List<String>> getMyFavData() async {
return Future.value(lst);
}
Future<void> deleteFromDataBase(int index) async {
Future.delayed(Duration(milliseconds: 500)).then((_) {
lst.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: getMyFavData(),
builder: (context, snapshot) {
if (snapshot.data == null)
return Container(
child: Center(
child:
CircularProgressIndicator(backgroundColor: Colors.red),
),
);
else
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Dismissible(
key: UniqueKey(),
onDismissed: (direction) async {
if (direction == DismissDirection.startToEnd) {
await deleteFromDataBase(index);
}
},
background: Container(
color: Colors.red,
alignment: Alignment.centerLeft,
child: Icon(
Icons.delete_forever,
color: Colors.white,
),
),
direction: DismissDirection.startToEnd,
child: Container(
width: MediaQuery.of(context).size.width,
child: Text(lst[index]),
color: Colors.blue,
margin: EdgeInsets.all(5.0),
));
});
}),
),
);
}
}
您应该避免在构建方法中分配未来。在 initState 中保存一个实例,因为每次构建树时都会重新构建 future。
Future myCachedFuture;
@override
void initState() {
super.initState();
myCachedFuture = getMyFavData();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(future: myCachedFuture,)
}