flutter - 如何将小部件删除安排为未来事件?
问题描述
我正在寻找一种在未来进行小部件删除的方法。
通过示例(和 MWE)来描述问题是最容易的。
向用户呈现几个AnimatedPositioned
容器,代表一个纸牌游戏。
这PositionedContainer
部分意味着每张卡都可以用于 Gin Rummy、Bridge 或实际上任何抽象数字纸牌游戏。
当用户点击一张卡片时,卡片向上滑动(使用 的Animated
部分AnimatedContainer
)
然后我们希望卡片从小部件堆栈中移除,即“消失”(而不仅仅是通过不透明度隐藏)
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Cards'),
),
body: Center(
child: Container(
alignment: Alignment.center,
child: CardGameWidget(),
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
),
),
),
);
}
}
class CardGameWidget extends StatefulWidget {
@override
CardGameWidgetState createState() => CardGameWidgetState();
}
class CardGameWidgetState extends State<CardGameWidget> {
List<Card> cards = [];
CardGameWidgetState() {
for (var i = 0; i < 5; ++i) {
this.cards.add(Card(
offset: Offset(i * 100.0, 200),
number: Random().nextInt(1 << 16))
);
}
}
Function onTap(int index) => (newOffset) {
setState(() {
cards[index].offset += Offset(0,-100);
});
};
@override
Widget build(BuildContext context) {
List<CardWidget> cardWidgets = [];
for (int i = 0; i < this.cards.length; ++i) {
cardWidgets.add(CardWidget(
onTap: onTap(i),
offset: this.cards[i].offset,
number: this.cards[i].number,
));
}
return Stack(children: cardWidgets);
}
}
class Card {
Card({this.offset, this.number});
Offset offset;
int number;
}
class CardWidget extends StatelessWidget {
CardWidget({
Key key,
this.onTap,
this.offset,
this.number,
});
final Function onTap;
final Offset offset;
final int number;
_handleTap(details) {
onTap(details.globalPosition);
}
@override
Widget build(BuildContext context) {
return AnimatedPositioned(
left: this.offset.dx,
top: this.offset.dy,
width: 100,
height: 100,
duration: Duration(seconds: 1),
child: GestureDetector(
onTapUp: _handleTap,
child: Container(
color: Colors.cyan,
padding: EdgeInsets.all(10),
margin: EdgeInsets.all(10),
child: FittedBox(
clipBehavior: Clip.antiAlias,
alignment: Alignment.centerLeft,
fit: BoxFit.contain,
child: Text(this.number.toString()),
))),
);
}
}
在动画完成后,如何将小部件删除安排为将来的事件?
解决方案
您可以查看AnimatedList:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue, brightness: Brightness.dark),
home: SimpleAnimatedList(),
);
}
}
class SimpleAnimatedList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SliceAnimatedList(),
);
}
}
class SliceAnimatedList extends StatefulWidget {
@override
_SliceAnimatedListState createState() => _SliceAnimatedListState();
}
class _SliceAnimatedListState extends State<SliceAnimatedList> {
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
List<int> _items = [];
int counter = 0;
Widget slideIt(BuildContext context, int index, animation) {
int item = _items[index];
TextStyle textStyle = Theme.of(context).textTheme.headline4;
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1, 0),
end: Offset(0, 0),
).animate(animation),
child: SizedBox(
height: 128.0,
child: Card(
color: Colors.primaries[item % Colors.primaries.length],
child: Center(
child: Text('Item $item', style: textStyle),
),
),
),
);
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Container(
height: double.infinity,
child: AnimatedList(
key: listKey,
initialItemCount: _items.length,
itemBuilder: (context, index, animation) {
return slideIt(context, index, animation);
},
),
),
),
Container(
decoration: BoxDecoration(color: Colors.greenAccent),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
onPressed: () {
setState(() {
listKey.currentState.insertItem(0,
duration: const Duration(milliseconds: 500));
_items = []
..add(counter++)
..addAll(_items);
});
},
child: Text(
"Add item to first",
style: TextStyle(color: Colors.black, fontSize: 20),
),
),
FlatButton(
onPressed: () {
if (_items.length <= 1) return;
listKey.currentState.removeItem(
0, (_, animation) => slideIt(context, 0, animation),
duration: const Duration(milliseconds: 500));
setState(() {
_items.removeAt(0);
});
},
child: Text(
"Remove first item",
style: TextStyle(color: Colors.black, fontSize: 20),
),
)
],
),
),
],
);
}
}
推荐阅读
- python - 如何使用 PyGame 为蛇和梯子创建 10x10 棋盘?
- python - 将数字四舍五入为 3 sig figs python
- google-apps-script - 由工作表中出现的新行触发的脚本
- c# - .Net Core 中的 AES IGE(无限乱码扩展)模式
- css - 未知高度的弹性父项中的一个纵横比子项
- angular - Angular 8 - ngx-DataTable 不显示数据
- php - 您如何通过 PHP 中的 API 检索 google 日历的嵌入链接
- mysql - 当满足要求时,Mysql 将布尔值设置为 1 所有其他要求为 0
- http - 限制 HTTP POST 方法的响应正文大小
- c# - 在 ASP.Net Zero 中,为什么当我尝试使用 Angular UI 执行 API 时没有获取记录,但是当我使用 swagger 时它返回预期值?