【问题标题】:Flutter - Change the animation of TabBarViewFlutter - 改变 TabBarView 的动画
【发布时间】:2019-03-24 04:23:08
【问题描述】:

我用 DefaultTabController 实现了一个基本的 TabBar 和 TabBarView,见下面的代码。

class MyApp2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: BOTTOM_TABS,
      child: Scaffold(
        appBar: AppBar(title: const Text('Bottom App Bar')),
        body: _tabBarView(),
        bottomNavigationBar: _bottomTabBar(),
      ),
    );
  }

  _tabBarView() {
    return TabBarView(
      physics: NeverScrollableScrollPhysics(),
      children: [
        Container(
          color: Colors.blue,
        ),
        Container(
          color: Colors.orange,
        ),
        Container(
          color: Colors.lightGreen,
        ),
        Container(
          color: Colors.red,
        ),
      ],
    );
  }

  _bottomTabBar() {
    return TabBar(
      tabs: [
        Tab(
          icon: new Icon(Icons.home),
        ),
        Tab(
          icon: new Icon(Icons.public),
        ),
        Tab(
          icon: new Icon(Icons.group),
        ),
        Tab(
          icon: new Icon(Icons.person),
        )
      ],
    );
  }
}

效果很好!现在我要做的是从默认动画更改两个选项卡之间的动画。但我找不到一个简单的方法来做到这一点。

经过一番研究,我似乎需要使用自定义 TabController 并以某种方式使用它的 animateTo 方法。对我来说,这似乎是一个相当大的改变,只是为了改变动画。 我想知道这是否是正确的方法,或者我是否缺少一些更简单的方法来更改选项卡视图之间的默认动画?

如果有人能给我一些很好的资源来为我指明正确的方向,我将不胜感激。

【问题讨论】:

标签: flutter flutter-layout flutter-animation


【解决方案1】:

这并不难,只需使用 TabController(要做到这一点,您需要使用 SingleTickerProviderStateMixin )和 AnimatedBuilder。

class MyApp2 extends StatefulWidget {
  @override
  _MyApp2State createState() => _MyApp2State();
}

class _MyApp2State extends State<MyApp2> with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    _tabController = TabController(length: 4, vsync: this);
    super.initState();
  }

  _tabBarView() {
    return AnimatedBuilder(
      animation: _tabController.animation,
      builder: (BuildContext context, snapshot) {
        return Transform.rotate(
          angle: _tabController.animation.value * pi,
          child: [
            Container(
              color: Colors.blue,
            ),
            Container(
              color: Colors.orange,
            ),
            Container(
              color: Colors.lightGreen,
            ),
            Container(
              color: Colors.red,
            ),
          ][_tabController.animation.value.round()],
        );
      },
    );
  }

  _bottomTabBar() {
    return TabBar(
      controller: _tabController,
      labelColor: Colors.black,
      tabs: [
        Tab(
          icon: new Icon(Icons.home),
        ),
        Tab(
          icon: new Icon(Icons.public),
        ),
        Tab(
          icon: new Icon(Icons.group),
        ),
        Tab(
          icon: new Icon(Icons.person),
        )
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 4,
      child: Scaffold(
        appBar: AppBar(title: const Text('Bottom App Bar')),
        body: _tabBarView(),
        bottomNavigationBar: _bottomTabBar(),
      ),
    );
  }
}

【讨论】:

  • _tabBarView 函数内的 Transform.rotate() 中的双数组是什么意思?是不是像多维数组?
  • 它不是双数组。第一个括号是选项卡列表,第二个括号是当前选项卡的索引。
  • 如果你想根本没有动画,这种方法也有用吗?
  • 那么你不需要tabview,只需将所有tabs widgets添加到一个列表中,并将tabController.index保存在状态中。要做到这一点,您需要将Listener添加到tabController,并在indexIsChanging时保存索引,类似的想法在这里stackoverflow.com/questions/52547731/…,但您不需要索引堆栈...
  • 这是网络上的几个工作示例之一,谢谢
【解决方案2】:

不知道你要不要彻底改变动画。

但是,如果您只需要一些自定义,您是否尝试使用 TabController 而不是 DefaultTabController ? 您只需将tabController 作为参数传递给TabBarTabBarView

要使用tabController 自定义动画,您应该为tabController 指定一个动画,并使用tabControlleranimateTo 函数指定曲线和持续时间。

https://api.flutter.dev/flutter/material/TabController/animateTo.html https://api.flutter.dev/flutter/material/TabController-class.html

【讨论】:

    【解决方案3】:

    屏幕截图(Null 安全):


    代码:

    如果你想要细粒度的控制,你可以使用AnimationController

    class _MyPageState extends State<MyPage> with TickerProviderStateMixin {
      late final TabController _tabController;
      late final AnimationController _controller;
    
      @override
      void initState() {
        super.initState();
    
        _controller = AnimationController(
          vsync: this,
          duration: Duration(milliseconds: 400),
          value: 1,
        );
    
        _tabController = TabController(
          length: 3,
          vsync: this,
        )..addListener(() {
            if (_tabController.indexIsChanging) {
              setState(() => _controller.forward(from: 0.5));
            }
          });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ScaleTransition(
            scale: _controller,
            child: [
              Container(color: Colors.red),
              Container(color: Colors.green),
              Container(color: Colors.blue),
            ][_tabController.index],
          ),
          bottomNavigationBar: TabBar(
            controller: _tabController,
            tabs: [
              Tab(child: Text('Red')),
              Tab(child: Text('Green')),
              Tab(child: Text('Blue')),
            ],
          ),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-10-30
      • 2021-08-16
      • 2019-09-19
      • 2020-01-02
      • 2020-04-29
      • 2021-05-19
      • 2021-06-12
      • 2020-04-27
      • 1970-01-01
      相关资源
      最近更新 更多