Flutter - 更改TabBarView的动画

19

我使用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方法。对我来说,仅仅为了更改动画,就需要进行相当大的更改。 我想知道是否这是正确的方法,或者我是否错过了一些更轻松的方法来仅仅更改标签页之间的默认动画?

如果有人能够提供一些好的资源来指导我走向正确的方向,我将不胜感激。

4个回答

20
这很简单,只需使用 TabController (需要使用 SingleTickerProviderStateMixin ) 和 AnimatedBuilder。 enter image description here
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() 中,双重数组是什么意思?这类似于多维数组吗? - Sarvesh Dalvi
1
这不是双数组。第一个括号中是选项卡列表,第二个括号中是当前选项卡的索引。 - Kherel
如果你想完全没有动画,这种方法也有用吗? - Iván Yoed
如果您不需要TabView,则只需将所有选项卡小部件添加到列表中,并在状态中保存tabController.index。为此,您需要向tabController添加addListener,并在indexIsChanging时保存索引,类似的想法在这里https://dev59.com/7lQK5IYBdhLWcg3wDLvP,但您不需要indexed stack... - Kherel
这是网络上少数可用的示例之一,谢谢。 - Ehab Reda

2

通过将动画持续时间设置为零来禁用Flutter选项卡之间的动画,如下所示

    tabController = TabController(
    animationDuration: Duration.zero,
    length: 4, vsync: this, initialIndex: 0);

以后感谢我吧。


2

截图(空值安全):

在此输入图片描述


代码:

如果您想要精细控制,可以使用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')),
        ],
      ),
    );
  }
}

1

我不知道你是否想完全改变动画。

但如果你只需要一些自定义,你可以尝试使用 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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接