Flutter 应用程序中每个页面的多个脚手架

Posted

技术标签:

【中文标题】Flutter 应用程序中每个页面的多个脚手架【英文标题】:Multiple Scaffolds for each page inside a Flutter App 【发布时间】:2020-06-19 00:58:43 【问题描述】:

API 文档:https://api.flutter.dev/flutter/material/Scaffold-class.html 说:

Scaffold 被设计为单个顶层容器,用于 MaterialApp 并且通常不需要嵌套脚手架。为了 选项卡式 UI 中的示例,其中 bottomNavigationBar 是 TabBar,并且 body 是一个 TabBarView,你可能很想制作每个标签栏 查看具有不同标题 AppBar 的脚手架。会更好 为更新 AppBar 的 TabController 添加一个监听器。

这是否意味着Material App下只需要一个Scaffold,或者每个页面只需要一个父Scaffold。如果是第一个,我们如何导航?如果是以后,这是否意味着常见的AppBarBottomBar 在每次导航时都会重新渲染?最佳做法是什么。

【问题讨论】:

是后者。通常每页有 1 个 Scaffold,是的,这意味着 AppBar 被重新渲染,但这不是问题。 【参考方案1】:

这意味着,通常每个页面都应该有一个Scaffold(更准确地说,是每个Route/screen),并且您不应该嵌套Scaffolds。

在屏幕之间导航

比如看看这个可以在DartPad运行的sn-p:

import 'package:flutter/material.dart';

void main() 
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));


class FirstRoute extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () 
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
          ,
        ),
      ),
    );
  


class SecondRoute extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () 
            Navigator.pop(context);
          ,
          child: Text('Go back!'),
        ),
      ),
    );
  

在这里,您可以看到有两个不同的页面/Routes/screens,每个页面都有自己的Scaffold。我们使用Navigator 来回导航,因此我们的页面被添加到堆栈中,一个Scaffold 在另一个之上。没关系。

如果晚了,是不是意味着common AppBar和BottomBar在每次导航时都会重新渲染?

是的,但是当我们制作两个单独的屏幕时,这正是我们想要的,每个屏幕都有自己的Scaffold

在脚手架主体内导航/嵌套导航

另一方面,看看这个例子:

import 'package:flutter/material.dart';

void main() 
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));


class FirstRoute extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Scaffold(
        body: Center(
          child: RaisedButton(
            child: Text('Open route'),
            onPressed: () ,
          ),
        ),
      ),
    );
  

在这里,我们嵌套了两个Scaffolds,如您所见,第二个应用栏被绘制在第一个应用栏下方。这不是选项卡式或嵌套导航的最佳方法。如果要在Scaffold 的正文内导航,并根据内容更改应用栏,则首选使用TabControllers,例如DefaultTabController。看看这个例子:

import 'package:flutter/material.dart';

void main() 
  runApp(TabBarDemo());


class TabBarDemo extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            title: Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Icon(Icons.directions_car),
              Icon(Icons.directions_transit),
              Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  

如您所见,我们只使用了一个Scaffold,因为我们只处理一个屏幕,真的。碰巧我们想要显示内容页面并在Scaffold 的正文中导航。

结论

作为一般经验法则:每个Route/screen 只使用一个Scaffold。仅使用一个ScaffoldTabControllerIndexedStack 等小部件来导航单个屏幕正文内的内容。

【讨论】:

遇到底部导航栏怎么办。我有一个类,我正在返回脚手架,对于它的主体,我正在传递页面数组,其中每个页面还包含它自己的脚手架。可以吗?它正在工作,但我不确定它是否正确 不需要keys 吗?当我注意到此页面上没有提及或使用密钥时,尝试学习使用密钥的最佳实践。

以上是关于Flutter 应用程序中每个页面的多个脚手架的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 中从底部工作表到全屏脚手架

Flutter Web 持久标头

webpack4+react多页面架构

webpack4+react多页面架构

webpack4+react多页面架构

为啥我的应用程序不使用脚手架的身份页面?