flutter - 在按下另一个 Widget 时将 Widget 动画化回其预览状态
问题描述
我创建了一个选项卡小部件,可以按一个选项卡并突出显示和动画,但是在按下另一个选项卡后,预览选项卡应该动画回到它的预览状态。
使用打击代码在您的 IDE 上运行。
import 'package:flutter/material.dart';
class AnimatedTabsOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300.0,
height: 60.0,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black26,
offset: Offset(0, 3.5),
// spreadRadius: 0.0,
blurRadius: 4.0,
),
]),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
BuildTab(),
BuildTab(),
BuildTab(),
],
),
);
}
}
class BuildTab extends StatefulWidget {
@override
_BuildTabState createState() => _BuildTabState();
}
class _BuildTabState extends State<BuildTab>
with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;
bool isVisible = false;
bool setActiveBackgroundColor = false;
animateNow() {
controller =
AnimationController(duration: Duration(milliseconds: 200), vsync: this);
controller.forward();
animation = Tween<double>(begin: 50, end: 150).animate(controller)
..addListener(() => setState(() {
setActiveBackgroundColor = true;
isVisible = true;
}));
// ..addStatusListener((AnimationStatus status) {
// if (status == AnimationStatus.completed) {
// controller.reverse();
// setState(() {
// setActiveBackgroundColor = false;
// isVisible = false;
// });
// }
// });
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print(
"setActiveBackgroundColor $setActiveBackgroundColor, isVisible: $isVisible");
return InkWell(
key: UniqueKey(),
onTap: () => animateNow(),
child: Container(
width: animation?.value ?? 50,
height: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: setActiveBackgroundColor == true ? Colors.blue : Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.home),
Flexible(
child: Visibility(visible: isVisible, child: Text("Home")),
)
],
),
),
);
}
}
我尝试使用全局键,并以另一种方式调用回调函数,但它没有完成这项工作。
解决方案
更好用AnimatedContainer
。我简化了你的代码。有多种解决方案,一切都取决于你,但如果你只是那个功能,这是一个很好的模式,重建触发器最少:
class AnimatedTabsOne extends StatefulWidget {
@override
_AnimatedTabsOneState createState() => _AnimatedTabsOneState();
}
class _AnimatedTabsOneState extends State<AnimatedTabsOne> {
int index;
final myTabs = [BuildTab(), BuildTab(), BuildTab()];
@override
Widget build(BuildContext context) {
return Container(
width: 300.0,
height: 60.0,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black26,
offset: Offset(0, 3.5),
// spreadRadius: 0.0,
blurRadius: 4.0,
),
]),
child: Row(
children: List<Widget>.from(
myTabs.map((tab) {
final index = myTabs.indexOf(tab);
return GestureDetector(
child: BuildTab(isVisible: this.index == index),
onTap: () {
if (this.index != index) {
setState(() {
this.index = index;
});
}
},
);
}),
),
),
);
}
}
class BuildTab extends StatelessWidget {
final bool isVisible;
BuildTab({this.isVisible = false});
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: Duration(milliseconds: 200),
width: isVisible ? 150 : 50,
height: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: isVisible ? Colors.blue : Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.home),
Flexible(
child: Visibility(visible: isVisible, child: Text("Home")),
)
],
),
);
}
}
推荐阅读
- validation - 如何从聚合中验证
- angular - Angular 图像标签 src 绑定 localhost url
- javascript - 可以在fancytree上进行分页吗?
- javascript - Angular - 专注于具有 ngIf 的输入元素
- java - java.lang.IllegalArgumentException 映射在 Spring Restful 服务中没有“orderId”的值
- python - model.py 更改后 Django 站点预览未更新
- php - 使用值的 foreach 循环进行 Json 操作/过滤
- go - 无法从源安装 Go-Ipfs
- java - 放入 NestedScrollView 时,列表页面 RecyclerView 无限滚动不起作用
- java - Android - Firestore 使用 startAfter() 和 limit() 返回一个空查询