Flutter Scaffold 页面结构

Material是一套设计风格,提供了大量的小部件,这里用Material风格搭建一个常见的应用页面结构。

创建Material应用

dart 复制代码
import 'package:flutter/material.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 关闭debug条幅
      home: Center(
        child: Text("首页"),
      ),
    );
  }
}

这里实例化的MaterialApp,而不是一般的Center Widget。

使用图表 Icon

dart 复制代码
import 'package:flutter/material.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 关闭debug条幅
      home: Center(
        child: Icon(
          Icons.star,
          color: Colors.amber,
          size: 128,
        ),
      ),
    );
  }
}

这里用到了Icon

所有Icons:https://fonts.google.com/icons

使用按钮 ElevatedButton

Flutter 提供了多种按钮小部件,这里ElevatedButton以为例。

dart 复制代码
import 'package:flutter/material.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 关闭debug条幅
      home: Center(
          child: ElevatedButton(
              onPressed: () {
                print("点击了按钮!");
              },
              child: Text("一个按钮"))),
    );
  }
}

切换主题

定义两个主题样式

在app/themes/app_theme.dart下定义两个主题样式:一个浅色,一个深色。

dart 复制代码
import 'package:flutter/material.dart';

class AppTheme {
  static ThemeData light = ThemeData(
      primaryColor: Colors.deepPurpleAccent,
      colorScheme: ColorScheme.light(
        primary: Colors.deepPurpleAccent,
        secondary: Colors.amber,
      ));
  static ThemeData dark = ThemeData(
      primaryColor: Colors.deepPurpleAccent,
      colorScheme: ColorScheme.dark(
        primary: Colors.cyan,
        secondary: Colors.amber,
      ));
}

调用主题样式

用MaterialApp的theme和darkTheme分别调用浅色和深色主题样式。

dart 复制代码
import 'package:flutter/material.dart';
import 'package:package_name/app/themes/app_theme.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // 关闭debug条幅
      theme: AppTheme.light,
      darkTheme: AppTheme.dark,
      home: Center(
          child: ElevatedButton(
              onPressed: () {
                print("点击了按钮!");
              },
              child: Text("一个按钮"))),
    );
  }
}

在IOS的设置-开发者里设置深色外观:

Scaffold 页面结构

使用Scaffold小部件可以得到一个Material风格的页面结构,可以设置页面头部工具栏、页面主体、页面底部的导航栏、侧边抽屉、底部侧板、浮动按钮等。

dart 复制代码
import 'package:flutter/material.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: DefaultTabController(
          // 设置默认Tab控制器
          length: 2,
          child: Scaffold(
            backgroundColor: Colors.amber,
            // 页面主体
            body: TabBarView(children: [
              Icon(
                Icons.explore_outlined,
                size: 128,
                color: Colors.black12,
              ),
              Icon(
                Icons.local_fire_department,
                size: 128,
                color: Colors.black12,
              ),
            ]),
            appBar: AppBar(
              title: Text("页面标题"),
              leading: IconButton(
                  onPressed: () {
                    print("这是导航菜单");
                  },
                  icon: Icon(Icons.menu)),
              actions: [
                IconButton(
                    onPressed: () {
                      print("这是Action位置");
                    },
                    icon: Icon(Icons.more_horiz))
              ],
              bottom: TabBar(tabs: [
                // 设置标签栏
                Tab(
                  text: 'Tab1',
                ),
                Tab(
                  text: 'Tab2',
                )
              ]),
            ),
            bottomNavigationBar: BottomNavigationBar(items: [
              BottomNavigationBarItem(
                  icon: Icon(Icons.explore_outlined), label: "发现"),
              BottomNavigationBarItem(
                  icon: Icon(Icons.add_a_photo_outlined), label: "添加"),
              BottomNavigationBarItem(
                  icon: Icon(Icons.account_circle_outlined), label: "用户")
            ]),
          ),
        ));
  }
}

如果是VSCode编辑器,在StatelessWidget上按快捷键Ctrl/Command+.,执行Convert to StatefulWidget命令,可以把无状态小部件转换成有状态小部件。

dart 复制代码
import 'package:flutter/material.dart';

class App extends StatefulWidget {
  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp()
  }
}

有状态小部件多出一个_AppState状态类,用于管理状态,通过createState、setState来创建和设置状态。

激活底部导航

dart 复制代码
import 'package:flutter/material.dart';

class App extends StatefulWidget {
  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  int currentAppBottomNavigationBarItem = 0;
  void onTabAppBottomNavigationBarItem(int index) {
    setState(() {
      currentAppBottomNavigationBarItem = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: DefaultTabController(
          // 设置默认Tab控制器
          length: 2,
          child: Scaffold(
            backgroundColor: Colors.amber,
            // 页面主体
            body: TabBarView(children: [
              Icon(
                Icons.explore_outlined,
                size: 128,
                color: Colors.black12,
              ),
              Icon(
                Icons.local_fire_department,
                size: 128,
                color: Colors.black12,
              ),
            ]),
            appBar: AppBar(
              title: Text("页面标题"),
              leading: IconButton(
                  onPressed: () {
                    print("这是导航菜单");
                  },
                  icon: Icon(Icons.menu)),
              actions: [
                IconButton(
                    onPressed: () {
                      print("这是Action位置");
                    },
                    icon: Icon(Icons.more_horiz))
              ],
              bottom: TabBar(tabs: [
                // 设置标签栏
                Tab(
                  text: 'Tab1',
                ),
                Tab(
                  text: 'Tab2',
                )
              ]),
            ),
            bottomNavigationBar: BottomNavigationBar(
                currentIndex: currentAppBottomNavigationBarItem,
                onTap: onTabAppBottomNavigationBarItem,
                items: [
                  BottomNavigationBarItem(
                      icon: Icon(Icons.explore_outlined), label: "发现"),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.add_a_photo_outlined), label: "添加"),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.account_circle_outlined), label: "用户")
                ]),
          ),
        ));
  }
}

点击底部导航,切换显示小部件

dart 复制代码
  final pageMain = [
    TabBarView(children: [
      Icon(
        Icons.explore_outlined,
        size: 128,
        color: Colors.black12,
      ),
      Icon(
        Icons.local_fire_department,
        size: 128,
        color: Colors.black12,
      ),
    ]),
    Center(
      child: Icon(
        Icons.add_a_photo_outlined,
        size: 128,
        color: Colors.black12,
      ),
    ),
    Center(
      child: Icon(
        Icons.account_circle_outlined,
        size: 128,
        color: Colors.black12,
      ),
    )
  ];

首先定义三个小部件列表,然后在body里按照索引来调用。

dart 复制代码
body: pageMain.elementAt(currentAppBottomNavigationBarItem),

动态显示或隐藏AppBar

用showAppBar来决定是否显示appBar。

dart 复制代码
class _AppState extends State<App> {
  // 是否显示应用栏
  bool showAppBar = true;

  int currentAppBottomNavigationBarItem = 0;
  void onTabAppBottomNavigationBarItem(int index) {
    setState(() {
      currentAppBottomNavigationBarItem = index;
      // 第一个显示,其他不显示
      showAppBar = index == 0;
    }
dart 复制代码
appBar: showAppBar ? AppBar(...) : null,

appBar设置为null,就是隐藏。

FloatingActionButton 漂浮动作按钮

dart 复制代码
floatingActionButton: FloatingActionButton(
onPressed: () {
  print('这是漂浮动作按钮。');
},
child: Icon(Icons.share_outlined),
backgroundColor: Colors.black,
foregroundColor: Colors.white,
)

用Scaffold的floatingActionButton参数,可以设置漂浮动作按钮。

定义部件

上面的小部件都是放在一起,我们还可以把一些把页面的部分小部件单独放到一个文件里,这里以appBar为例:

app_page_header.dart

dart 复制代码
import 'package:flutter/material.dart';

class AppPageHeader extends StatelessWidget implements PreferredSizeWidget {
  @override
  final Size preferredSize = Size.fromHeight(100);
  @override
  Widget build(BuildContext context) {
    return AppBar(
      title: Text("页面标题"),
      leading: IconButton(
          onPressed: () {
            print("这是导航菜单");
          },
          icon: Icon(Icons.menu)),
      actions: [
        IconButton(
            onPressed: () {
              print("这是Action位置");
            },
            icon: Icon(Icons.more_horiz))
      ],
      bottom: TabBar(tabs: [
        // 设置标签栏
        Tab(
          text: 'Tab1',
        ),
        Tab(
          text: 'Tab2',
        )
      ]),
    );
  }
}

这里单独定义了一个AppPageHeader的类,作为appBar,然后我们就可以调用它了。

dart 复制代码
import 'package:package_name/app/components/app_page_header.dart';

appBar: showAppBar ? AppPageHeader() : null,

BottomSheet 底部面板

这里点击浮动按钮显示底部面板,把浮动按钮单独封装成了一个单独的文件app_floating_action_button.dart:

dart 复制代码
import 'package:flutter/material.dart';

class AppFloatingActionButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FloatingActionButton(
      onPressed: () {
        print('这是漂浮动作按钮。');
        showBottomSheet(
          context: context,
          builder: (BuildContext context) {
            return SizedBox.expand(
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    const Text('漂浮动作按钮'),
                    ElevatedButton(
                      child: const Text('关闭'),
                      onPressed: () => Navigator.pop(context),
                    ),
                  ],
                ),
              ),
            );
          },
        );
      },
      child: Icon(Icons.share_outlined),
      backgroundColor: Colors.black,
      foregroundColor: Colors.white,
    );
  }
}

调用:

dart 复制代码
floatingActionButton: AppFloatingActionButton(),

边栏抽屉

dart 复制代码
import 'package:flutter/material.dart';

class AppPageAside extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: Center(
        child: Text("边栏抽屉"),
      ),
    );
  }
}

在Scaffold函数里用drawer参数调用:

dart 复制代码
drawer: AppPageAside(),

AppBar leading 位置显示抽屉

dart 复制代码
onPressed: () {
  Scaffold.of(context).openDrawer();
},

设置边栏抽屉显示的内容

dart 复制代码
import 'package:flutter/material.dart';

class AppPageAside extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: Center(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            UserAccountsDrawerHeader(
                accountName: Text("姓名"), accountEmail: Text("[email protected]")),
            ListTile(
              title: Text(
                "评论",
                textAlign: TextAlign.right,
              ),
              trailing: Icon(Icons.comment_outlined),
            ),
            ListTile(
              title: Text(
                "账户",
                textAlign: TextAlign.right,
              ),
              trailing: Icon(Icons.account_box_outlined),
            ),
            ListTile(
              title: Text(
                "退出",
                textAlign: TextAlign.right,
              ),
              trailing: Icon(Icons.logout_outlined),
            ),
          ],
        ),
      ),
    );
  }
}

弹出菜单

dart 复制代码
import 'package:flutter/material.dart';

class AppPageHeaderActionsMore extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return PopupMenuButton(
      itemBuilder: (context) => [
        PopupMenuItem(
          value: 'stack',
          child: Icon(
            Icons.view_agenda_outlined,
            color: Colors.black12,
          ),
        ),
        PopupMenuItem(
          value: 'stack',
          child: Icon(
            Icons.dashboard_outlined,
            color: Colors.black12,
          ),
        ),
      ],
      icon: Icon(Icons.more_horiz),
      offset: Offset(0, 50),
      onCanceled: () {
        print("弹出菜单按钮");
      },
      onSelected: (value) {
        print("弹出菜单按钮的值是 $value");
      },
    );
  }
}
dart 复制代码
AppBar(
......
    actions: [
    AppPageHeaderActionsMore(),
    ]
......
相关推荐
getapi3 小时前
flutter底部导航代码解释
前端·javascript·flutter
初遇你时动了情3 小时前
安装fvm可以让电脑同时管理多个版本的flutter、flutter常用命令、vscode连接模拟器
flutter
RichardLai8819 小时前
[Flutter学习之Dart基础] - 控制语句
android·flutter
louisgeek1 天前
Flutter Channel 通信机制
flutter
浅忆无痕1 天前
Flutter空安全最小必备知识
android·前端·flutter
亚洲小炫风1 天前
flutter 打包mac程序 dmg教程
flutter·macos
亚洲小炫风1 天前
flutter 桌面应用之系统托盘
flutter·系统托盘
亚洲小炫风1 天前
flutter 桌面应用之右键菜单
flutter·桌面端·右键菜单·contextmenu
louisgeek2 天前
Flutter Widget、Element 和 RenderObject 的区别
flutter
顾林海2 天前
Flutter 文本组件深度剖析:从基础到高级应用
android·前端·flutter