本文最后更新于 576 天前
1. FractionallySizedBox
通过更改width/heightFactor来实现类似滚动进度条
Row(
children: [
Flexible(
child: FractionallySizedBox(
widthFactor: 1.0,
child: Container(
width: 20,
height: 20,
color: Colors.red,
),
),
),
Container(
width: 20,
height: 20,
color: Colors.blueAccent,
)
],
)
2. Align
类似折叠展开面板
ClipRect(
child: AnimatedBuilder(
builder: (BuildContext context, Widget? child) {
return Align(
alignment: Alignment.center,
heightFactor: _heightFactorMyopia.value,
child: Text("");
);
},
animation: _heightFactorMyopia,
),
)
3. Position
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{
late AnimationController _animationController;
late Animation<Offset> _animation;
@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: const Duration(seconds: 2), vsync: this);
// 初始化将其移动到屏幕外 ,不加动画默认就是右侧一个 widthFactor大小显示
_animation = Tween(begin: const Offset(1.0,0.0), end: const Offset(0.0,0.0)).animate(_animationController);
}
@override
void dispose() {
super.dispose();
_animationController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
floatingActionButton: FloatingActionButton(onPressed: () {
_animationController.forward();
}),
body: GestureDetector(
onHorizontalDragStart: (detail) {
},
onHorizontalDragUpdate: (detail) {
},
onHorizontalDragEnd: (detail) {
},
child: SizedBox(
width: double.infinity,
height: 50,
child: Stack(
children: [
Container(
color: Colors.black12,
width: double.infinity,
),
Positioned.fill(
child: ClipRect(
// 动态改变裁切比例
clipper: _SlidableClipper(animation: _animation),
// 占满宽度后 指定 widthFactor 并且通过alignment 为右侧
// 这样最终显示右侧 大小是 widthFactor
child: FractionallySizedBox(
alignment: const Alignment(1,0),
widthFactor: 0.15,
child: SlideTransition(
position: _animation,
child: Flex(
direction: Axis.horizontal,
children: [
Container(
color: Colors.pink,
width: 50,
height: 50,
child: const Center(child: Text("删除",style: TextStyle(
color: Colors.white
),)),
)
],
),
),
),
),
)
],
),
),
),
);
}
}
class _SlidableClipper extends CustomClipper<Rect> {
_SlidableClipper() : super();
@override
Rect getClip(Size size) {
// 与上面的widthFactor 相关 ratio = 1 - widthFactor
final double offset = 1.0 * size.width;
// 从左往右滑动 -0.0 ~ -(1 - widthFactor)
if (offset < 0) {
return Rect.fromLTRB(size.width + offset, 0, size.width, size.height);
}
// 从右往左滑动 (1 - widthFactor) ~ 1.0
return Rect.fromLTRB(0, 0, offset, size.height);
}
@override
Rect getApproximateClipRect(Size size) => getClip(size);
@override
bool shouldReclip(_SlidableClipper oldClipper) {
return true;
}
}