Flutter:动画化有状态小部件的问题

时间:2019-11-28 09:51:08

标签: animation flutter dart

我正在尝试在应用程序中使用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),
          )
        ],
      )
    );
  }
}

另一件事是,当您更改选项卡并且动画完成并且再次单击相同的选项卡按钮时,它将解决渲染问题。

0 个答案:

没有答案