在底部导航栏上推送新屏幕时出现颤振过渡动画问题

Posted

技术标签:

【中文标题】在底部导航栏上推送新屏幕时出现颤振过渡动画问题【英文标题】:Flutter Transition Animation Issue while pushing new screen on Bottom Navigation Bar 【发布时间】:2020-08-04 13:25:11 【问题描述】:

我有一个 MaterialApp,其中有一个 IndexedStack 作为其主页,用于 BottomBarNavigation。现在,在其中一个“选项卡”中,我希望像在 ios 中一样完成页面转换。

部分技巧可以使用 Navigator.push 中的 CupertinoPageRoute 完成,如下所示:

Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute<bool>(
      //fullscreenDialog: true,
      builder: (BuildContext context) => new DescriptionPage(),

    ));

这会导致新页面作为 iOS 应用程序从右侧滑动。但是,正如 CupertinoPageRoute 的文档中所说,我还希望将第一页向右移动视差:

当另一个页面进入覆盖它时,该页面也会以视差向左移动。

如果第一页本身是通过“Navigator.push(CupertinoPageRoute ...”创建的,这将完成,但正如我所提到的,我的第一页是应用程序主页的主要页面之一。

当前的过渡风格: the new page slides in from right, but the current page does not shift to left

如您所见,当前页面不会向左移动。可能有一种方法可以使当前页面的小部件充当由 CupertinoPageRoute 构建的小部件,以便当前页面本身在新页面进入时向左滑动。

【问题讨论】:

【参考方案1】:

在 MaterialApp 的theme: 参数中,试试这个:

MaterialApp(
  theme: ThemeData( //or replace with your custom ThemeData.copywith()
    pageTransitionsTheme: PageTransitionsTheme(
      builders: 
        TargetPlatform.android: CupertinoPageTransitionsBuilder(),
        TargetPlatform.iOS: CupertinoPageTransitionsBuilder()
      
    ),
  ),
)

【讨论】:

【参考方案2】:

如果您运行下面的代码,您将看到第一个选项卡正在执行您所看到的操作,而第二个选项卡是您所期望的。

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: CupertinoStoreHomePage(title: 'Flutter Demo Home Page'),
    );
  


class CupertinoStoreHomePage extends StatelessWidget 
  const CupertinoStoreHomePage(title);

  @override
  Widget build(BuildContext context) 
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.bell),
            title: Text('TAB1'),
          ),
          BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.bell_solid),
            title: Text('TAB2'),
          ),
        ],
      ),
      tabBuilder: (context, index) 
        switch (index) 
          case 0:
            return CupertinoTabView(builder: (context) 
              return CupertinoPageScaffold(
                child: TAB1(),
              );
            );
          case 1:
            return CupertinoTabView(
              builder: (context) 
                return CupertinoPageScaffold(
                  child: TAB2(),
                );
              ,
              routes: 
                '/screen': (ctx) => NextScreen(),
              ,
            );

          default:
            return Container();
        
      ,
    );
  


class TAB1 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("TAB1"),
      ),
      body: Container(
        child: FlatButton(
          child: Text("Go To Next Screen"),
          onPressed: () => Navigator.of(context)
              .push(MaterialPageRoute(builder: (_) => NextScreen())),
        ),
      ),
    );
  


class TAB2 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("TAB2"),
      ),
      body: Container(
          child: FlatButton(
        child: Text("Go To Next Screen"),
        onPressed: () => Navigator.of(context).pushNamed("/screen"),
      )),
    );
  


class NextScreen extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return CupertinoPageScaffold(
      child: Scaffold(
        appBar: AppBar(
          title: Text("NextScreen"),
        ),
        body: Container(
          child: Text("NextScreen"),
        ),
      ),
    );
  

当使用 Navigator.of(ctx).push 时,应用程序会尝试在根导航器上推送新屏幕,在您的情况下是标签栏,但它无法替换标签栏,因此您会看到不完整的动画。但是在第二种方法中,您在相关选项卡中定义了路由并使用 Push Named,应用程序使用分配给该选项卡的导航器,从而获得预期的结果。

编码愉快!

【讨论】:

以上是关于在底部导航栏上推送新屏幕时出现颤振过渡动画问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在导航控制器中将过渡动画从底部更改为顶部?

从大标题页过渡到小标题页时出现导航间隙

将 appbarLayout 放在屏幕底部

如何单击底部栏上的图标

在Android中使用导航组件时如何删除默认动画过渡?

尝试对底部导航进行意图时出现此错误