Flutter Scaffold 页面结构

devtools/2025/2/4 6:18:16/

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

创建Material应用

import 'package:flutter/material.dart';class App extends StatelessWidget {Widget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false, // 关闭debug条幅home: Center(child: Text("首页"),),);}
}

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

使用图表 Icon

import 'package:flutter/material.dart';class App extends StatelessWidget {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
1

使用按钮 ElevatedButton

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

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

1

切换主题

定义两个主题样式

在app/themes/app_theme.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分别调用浅色和深色主题样式。

import 'package:flutter/material.dart';
import 'package:package_name/app/themes/app_theme.dart';class App extends StatelessWidget {Widget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false, // 关闭debug条幅theme: AppTheme.light,darkTheme: AppTheme.dark,home: Center(child: ElevatedButton(onPressed: () {print("点击了按钮!");},child: Text("一个按钮"))),);}
}

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

Scaffold 页面结构

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

import 'package:flutter/material.dart';class App extends StatelessWidget {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: "用户")]),),));}
}

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

import 'package:flutter/material.dart';class App extends StatefulWidget {State<App> createState() => _AppState();
}class _AppState extends State<App> {Widget build(BuildContext context) {return MaterialApp(}
}

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

激活底部导航

import 'package:flutter/material.dart';class App extends StatefulWidget {State<App> createState() => _AppState();
}class _AppState extends State<App> {int currentAppBottomNavigationBarItem = 0;void onTabAppBottomNavigationBarItem(int index) {setState(() {currentAppBottomNavigationBarItem = index;});}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: "用户")]),),));}
}

1

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

  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里按照索引来调用。

body: pageMain.elementAt(currentAppBottomNavigationBarItem),

1

动态显示或隐藏AppBar

用showAppBar来决定是否显示appBar。

class _AppState extends State<App> {// 是否显示应用栏bool showAppBar = true;int currentAppBottomNavigationBarItem = 0;void onTabAppBottomNavigationBarItem(int index) {setState(() {currentAppBottomNavigationBarItem = index;// 第一个显示,其他不显示showAppBar = index == 0;}
appBar: showAppBar ? AppBar(...) : null,

appBar设置为null,就是隐藏。

FloatingActionButton 漂浮动作按钮

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

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

定义部件

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

app_page_header.dart

import 'package:flutter/material.dart';class AppPageHeader extends StatelessWidget implements PreferredSizeWidget {final Size preferredSize = Size.fromHeight(100);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,然后我们就可以调用它了。

import 'package:package_name/app/components/app_page_header.dart';appBar: showAppBar ? AppPageHeader() : null,

BottomSheet 底部面板

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

import 'package:flutter/material.dart';class AppFloatingActionButton extends StatelessWidget {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,);}
}

调用:

floatingActionButton: AppFloatingActionButton(),

1

边栏抽屉

import 'package:flutter/material.dart';class AppPageAside extends StatelessWidget {Widget build(BuildContext context) {return Drawer(child: Center(child: Text("边栏抽屉"),),);}
}

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

drawer: AppPageAside(),

1

AppBar leading 位置显示抽屉

onPressed: () {Scaffold.of(context).openDrawer();
},

设置边栏抽屉显示的内容

import 'package:flutter/material.dart';class AppPageAside extends StatelessWidget {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),),],),),);}
}

1

弹出菜单

import 'package:flutter/material.dart';class AppPageHeaderActionsMore extends StatelessWidget {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");},);}
}
AppBar(
......actions: [AppPageHeaderActionsMore(),]
......

http://www.ppmy.cn/devtools/155925.html

相关文章

PyCharm中使用Ollama安装和应用Deepseek R1模型:完整指南

引言 人工智能和大型语言模型正在改变我们与技术交互的方式。Deepseek R1是一个强大的AI模型,而Ollama则是一个让我们能够轻松在本地运行这些模型的工具。本文将指导您如何使用Ollama安装Deepseek R1模型,并在PyCharm中创建一个简单的聊天应用。 © ivwdcwso (ID: u0121…

爱普生L3153打印机无线连接配置流程

家里使用的是移动宽带中兴路由器&#xff0c;有WPS功能&#xff0c;进入192.168.1.1管理员页面&#xff0c;用户名user&#xff0c;密码在路由器背面&#xff08;可以登录后修改密码&#xff09;。在网络-WLAN网络配置-WPS中&#xff0c;点击push button&#xff0c;激活路由器…

Redis 数据备份与恢复

Redis 数据备份与恢复 引言 Redis 是一款高性能的键值对存储系统,广泛应用于缓存、消息队列、分布式锁等领域。为了保证数据的安全性和可靠性,定期对 Redis 数据进行备份与恢复是至关重要的。本文将详细介绍 Redis 数据备份与恢复的方法,帮助您更好地管理和维护 Redis 数据…

低代码系统-产品架构案例介绍、炎黄盈动-易鲸云(十二)

易鲸云作为炎黄盈动新推出的产品&#xff0c;在定位上为低零代码产品。 开发层 表单引擎 表单设计器&#xff0c;包括设计和渲染 流程引擎 流程设计&#xff0c;包括设计和渲染&#xff0c;需要说明的是&#xff1a;采用国际标准BPMN2.0&#xff0c;可以全球通用 视图引擎 视图…

【Validator】字段验证器struct与多层级验证,go案例

标签用法总结表 标签功能代码实例required字段必填Name string \v:“required”alphaunicode验证字段是否只包含字母和 Unicode 字符Name string \v:“alphaunicode”gte验证字段值是否大于等于指定值Age uint8 \v:“gte10”lte验证字段值是否小于等于指定值Age uint8 \v:“lt…

Windows 安装Linux子系统

文章目录 一、启用虚拟化二、安装子系统1. 查看所有官方支持的 WSL 发行版2. 安装 Ubuntu3. 安装非官方发行版(如 CentOS)三、启动和更新子系统1. 启动Ubuntu终端2. 更新系统四、管理已安装的发行版在 Windows 的 WSL(Windows Subsystem for Linux)中,除了 Ubuntu,你还可…

MATLAB-Simulink并行仿真示例

一、概述 在进行simulink仿真的过程中常常遇到CPU利用率较低&#xff0c;仿真缓慢的情况&#xff0c;可以借助并行仿真改善这些问题&#xff0c;其核心思想是将参数扫描、蒙特卡洛分析或多工况验证等任务拆分成多个子任务&#xff0c;利用多核CPU或计算集群的并行计算能力&…

《苍穹外卖》项目学习记录-Day7缓存套餐

如果使用EHCache作为缓存实现&#xff0c;只需要导入 EHCache的maven坐标。 入门案例 如果使用Spring cache缓存数据&#xff0c;key的生成&#xff1a;userCache::xxx。#user.id中的.叫做对象导航。 因为id是自增的所以只输入age和name就可以了&#xff0c;在插入完之后它会把…