我正在尝试在应用程序中使用flutter gallery bottom navigation demo动画。但是不同之处在于我所有的选项卡都是有状态的小部件。但是该动画不适用于有状态的小部件,并且更改选项卡时会出现错误,并且更改状态时不会重新渲染选项卡。这是一个演示代码:
import 'package:flutter/material.dart';
main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainView(),
);
}
}
class MainView extends StatefulWidget {
MainView({Key key}) : super(key: key);
@override
_MainViewState createState() => _MainViewState();
}
class _MainViewState extends State<MainView> with TickerProviderStateMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
int _selectedIndex = 0;
List<_TabView> _views;
@override
void dispose() {
for (_TabView view in _views)
view.controller.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_views = <_TabView>[
_TabView(
title: 'Home',
icon: Icons.home,
child: DemoPage(Icons.home, 'Home'),
vsync: this,
),
_TabView(
title: 'Sales',
icon: Icons.attach_money,
child: DemoPage(Icons.attach_money, 'Sales'),
vsync: this,
),
_TabView(
title: 'Expenses',
icon: Icons.money_off,
child: DemoPage(Icons.money_off, 'Expenses'),
vsync: this,
),
_TabView(
title: 'Products',
icon: Icons.shopping_cart,
child: DemoPage(Icons.shopping_cart, 'Products'),
vsync: this,
),
_TabView(
title: 'Customers',
icon: Icons.supervised_user_circle,
child: DemoPage(Icons.supervised_user_circle, 'Customers'),
vsync: this,
),
];
_views[_selectedIndex].controller.value = 1.0;
}
void _onItemTapped(int index) {
setState(() {
_views[_selectedIndex].controller.reverse();
_selectedIndex = index;
_views[_selectedIndex].controller.forward();
});
// _views[_selectedIndex].controller.addStatusListener((status) {
// if (status == AnimationStatus.completed) setState(() {});
// });
}
Widget _buildTransitionsStack() {
final List<FadeTransition> transitions = <FadeTransition>[
for (_TabView view in _views) view.transition(),
];
transitions.sort((FadeTransition a, FadeTransition b) {
final Animation<double> aAnimation = a.opacity;
final Animation<double> bAnimation = b.opacity;
final double aValue = aAnimation.value;
final double bValue = bAnimation.value;
return aValue.compareTo(bValue);
});
return Stack(children: transitions);
}
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text('Bottom Navigation Demo')),
bottomNavigationBar: _buildBottomNavigationBar(),
body: Center(
child: _buildTransitionsStack(),
),
),
);
}
BottomNavigationBar _buildBottomNavigationBar() {
return BottomNavigationBar(
unselectedItemColor: Colors.grey[700],
elevation: 5,
items: <BottomNavigationBarItem>[
for (_TabView view in _views) view.item
],
type: BottomNavigationBarType.fixed,
currentIndex: _selectedIndex,
onTap: _onItemTapped,
);
}
}
class _TabView {
_TabView({
IconData icon,
Widget child,
String title,
TickerProvider vsync,
}) : _child = child,
item = BottomNavigationBarItem(
icon: Icon(icon),
title: Text(title),
),
controller = AnimationController(
duration: Duration(milliseconds: 300),
vsync: vsync,
) {
_animation = controller.drive(CurveTween(
curve: const Interval(0.5, 1.0, curve: Curves.fastOutSlowIn),
));
}
final Widget _child;
final BottomNavigationBarItem item;
final AnimationController controller;
Animation<double> _animation;
FadeTransition transition() {
return FadeTransition(
opacity: _animation,
child: SlideTransition(
position: _animation.drive(
Tween<Offset>(
begin: const Offset(0.0, 0.02), // Slightly down.
end: Offset.zero,
),
),
child: _child,
),
);
}
}
class DemoPage extends StatefulWidget {
DemoPage(this.icon, this.string);
final IconData icon;
final String string;
@override
_DemoPageState createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
bool clicked = false;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
Icon(widget.icon),
Text(clicked ? 'Clicked' : widget.string),
FlatButton(
child: Text('click here'),
onPressed: () => setState(() => clicked = !clicked),
)
],
)
);
}
}
另一件事是,当您更改选项卡并且动画完成并且再次单击相同的选项卡按钮时,它将解决渲染问题。