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("abc@domain.com")),
            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(),
    ]
......
相关推荐
亚历克斯神8 小时前
Flutter for OpenHarmony: Flutter 三方库 mutex 为鸿蒙异步任务提供可靠的临界资源互斥锁(并发安全基石)
android·数据库·安全·flutter·华为·harmonyos
钛态8 小时前
Flutter 三方库 smartstruct 鸿蒙化字段映射适配指南:介入静态预编译引擎扫除视图及数据模型双向强转类型错乱隐患,筑稳如磐石的企业级模型治理防线-适配鸿蒙 HarmonyOS ohos
flutter·华为·harmonyos
键盘鼓手苏苏8 小时前
Flutter 组件 csv2json 适配鸿蒙 HarmonyOS 实战:高性能异构数据转换,构建 CSV 流式解析与全栈式数据映射架构
flutter·harmonyos·鸿蒙·openharmony
左手厨刀右手茼蒿8 小时前
Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构
网络·flutter·http
雷帝木木8 小时前
Flutter 三方库 hrk_logging 的鸿蒙化适配指南 - 实现标准化分层日志记录、支持多目的地输出与日志分级过滤
flutter·harmonyos·鸿蒙·openharmony·hrk_logging
左手厨刀右手茼蒿8 小时前
Flutter 三方库 dio_compatibility_layer 的鸿蒙化适配指南 - 实现 Dio 跨主版本的平滑迁移、支持遗留拦截器兼容与网络请求架构稳定升级
flutter·harmonyos·鸿蒙·openharmony·dio_compatibility_layer
雷帝木木8 小时前
Flutter 三方库 hashids2 基于鸿蒙安全内核的深度隐匿映射适配:数字指纹泄露防御层、生成短小精悍唯一不可逆加盐哈希,护航全链路请求 URL 隐私-适配鸿蒙 HarmonyOS ohos
安全·flutter·harmonyos
王码码203511 小时前
Flutter 组件 inappwebview_cookie_manager 适配 鸿蒙Harmony 实战 - 驾驭核心大 Web 容器缓存隧道、构建金融级政企应用绝对防串号跨域大隔离基座
flutter·harmonyos·鸿蒙·openharmony·inappwebview_cookie_manager
左手厨刀右手茼蒿11 小时前
Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 驾驭企业级 Exchange Web Services 协议、实现鸿蒙端政企办公同步与高安通讯隔离方案
flutter·harmonyos·鸿蒙·openharmony
钛态11 小时前
Flutter 三方库 react 泛前端核心范式框架鸿蒙原生层生态级双向超能适配:跨时空重塑响应式单向数据流拓扑与高度精密生命周期树引擎解耦视图渲染控制中枢(适配鸿蒙 HarmonyOS ohos)
前端·flutter·react.js