【Flutter】有状态组件StatefulWidgetScaffold组件属性

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Flutter学习
🌠 首发时间:2024年5月26日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾

目录

  • 有状态组件StatefulWidget
    • 实现计数器功能
    • 实现动态列表
  • Scaffold属性:BottomNavigationBar
    • 组件介绍
    • 自定义底部导航
    • 底部菜单选中
    • 自定义底部导航实现页面切换
  • Scaffold属性:FloatingActionButton
    • FloatingActionButton详解
    • 实现类似闲鱼App底部导航凸起按钮
  • Scaffold属性:抽屉菜单Drawer
    • DrawerHeader
    • UserAccountsDrawerHeader

有状态组件StatefulWidget

Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget / StatefulWidget

  • StatelessWidget 是无状态组件,状态不可变的 widget
  • StatefulWidget 是有状态组件,持有的状态可能在 widget 生命周期改变
  • 通俗的讲:如果我们想改变页面中的数据的话,这个时候就需要用到 StatefulWidget

实现计数器功能

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const HomePage(),);}
}class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {int _numCount = 0; //计数Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("flutter App"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("$_numCount",style: Theme.of(context).textTheme.headlineMedium,),const SizedBox(height: 60),ElevatedButton(onPressed: () {setState(() {_numCount++;});},child: const Text("增加"))],),),//Scaffold组件中自带的浮动按钮floatingActionButton: FloatingActionButton(onPressed: () {setState(() {_numCount++;});},child: const Icon(Icons.add),),);}
}

在使用 StatefulWidget 后,建议我们代码的框架写成上面这样,将 Scaffold 组件写到自定义组件中,这样我们可以使用其在有状态组件中的一些属性

在这里插入图片描述

实现动态列表

需求:实现通过点击按钮就能添加列表项的效果

class _HomePageState extends State<HomePage> {final List<String> _list = []; //final修饰的列表可以增加元素Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("动态列表"),),floatingActionButton: FloatingActionButton(onPressed: () {setState(() {_list.add("我是一个新增的列表");});},child: const Icon(Icons.add),),body: ListView(children: _list.map((e) {return ListTile(title: Text(e),);}).toList(),),);}
}

在这里插入图片描述

Scaffold属性:BottomNavigationBar

组件介绍

BottomNavigationBar 是底部导航条,可以让我们定义底部 Tab 切换,bottomNavigationBarScaffold 组件的参数。

BottomNavigationBar 常见的属性

属性名说明
itemsList 底部导航条按钮集合
iconSizeicon
currentIndex默认选中第几个
onTap选中变化回调函数
fixedColor选中的颜色
type底部超过4个菜单必须配置这个属性:ButtomNavigationBarType.fixedButtomNavigationBarType.shifting

自定义底部导航

实现如下效果:

在这里插入图片描述

class _HomePageState extends State<HomePage> {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("自定义底部导航"),),body: const Center(child: Text("我是一个文本")),bottomNavigationBar: BottomNavigationBar(items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),],),);}
}

底部菜单选中

前面自定义的底部导航还没有完整实现,一般要求我们点击哪个菜单,哪个菜单就会显示选中的效果,下面我们来实现这个效果

在这里插入图片描述

class _HomePageState extends State<HomePage> {int _currentIndex = 0; //当前选中索引Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("自定义底部导航"),),body: const Center(child: Text("我是一个文本")),bottomNavigationBar: BottomNavigationBar(currentIndex: _currentIndex,fixedColor: Colors.blue,onTap: (value) {setState(() {_currentIndex = value;});},items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),],),);}
}

自定义底部导航实现页面切换

为了让代码条理更加清晰,我们将每个页面分文件写。

lib 目录下新建目录 pages,在 pages 下新建文件 tabs.dart 和文件夹 tabs,在 tabs 下新建 3 个页面对应的文件:

在这里插入图片描述

home.dart

import 'package:flutter/material.dart';class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {Widget build(BuildContext context) {return const Center(child: Text("首页"),);}
}

category.dart

import 'package:flutter/material.dart';class CategoryPage extends StatefulWidget {const CategoryPage({super.key});State<CategoryPage> createState() => _CategoryPageState();
}class _CategoryPageState extends State<CategoryPage> {Widget build(BuildContext context) {return const Center(child: Text("分类"),);}
}

setting.dart

import 'package:flutter/material.dart';class SettingPage extends StatefulWidget {const SettingPage({super.key});State<SettingPage> createState() => _SettingPageState();
}class _SettingPageState extends State<SettingPage> {Widget build(BuildContext context) {return const Center(child: Text("系统设置"),);}
}

tabs.dart:前面页面切换的代码

import 'package:flutter/material.dart';
import './tabs/home.dart';
import './tabs/category.dart';
import './tabs/setting.dart';class Tabs extends StatefulWidget {const Tabs({super.key});State<Tabs> createState() => _TabsState();
}class _TabsState extends State<Tabs> {int _currentIndex = 0; //当前选中索引final List<Widget> _pages = const [HomePage(),CategoryPage(),SettingPage(),];Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("自定义底部导航"),),body: _pages[_currentIndex], //自动切换页面bottomNavigationBar: BottomNavigationBar(currentIndex: _currentIndex,fixedColor: Colors.blue,onTap: (value) {setState(() {_currentIndex = value;});},items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),],),);}
}

main.dart

import 'package:flutter/material.dart';
import 'pages/tabs.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),debugShowCheckedModeBanner: false,home: const Tabs(),);}
}

在这里插入图片描述

Scaffold属性:FloatingActionButton

FloatingActionButton详解

FloatingActionButton 简称 FAB ,可以实现浮动按钮,也可以实现类似闲鱼app的底部凸起导航

属性名称属性值
child子视图,一般为 Icon,不推荐使用文字
tooltipFAB被长按时显示,也是无障碍功能
backgroundColor背景颜色
elevation未点击时的阴影
highlightElevation点击时阴影值,默认12
onPressed点击事件回调
shape可以定义FAB的形状等
mini是否为 mini 类型,默认为 false

实现类似闲鱼App底部导航凸起按钮

我们在前面自定义底部导航的代码稍加修改,再添加一个浮动按钮即可实现类似闲鱼底部导航效果:

在这里插入图片描述

这里给出 tabs.dart 的代码,其中 message.dartuser.dart 两个页面内容和其他页面类似

import 'package:flutter/material.dart';
import './tabs/home.dart';
import './tabs/category.dart';
import './tabs/setting.dart';
import './tabs/message.dart';
import './tabs/user.dart';class Tabs extends StatefulWidget {const Tabs({super.key});State<Tabs> createState() => _TabsState();
}class _TabsState extends State<Tabs> {int _currentIndex = 0; //当前选中索引final List<Widget> _pages = const [HomePage(),CategoryPage(),MessagePage(),SettingPage(),UserPage(),];Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("浮动按钮"),),body: _pages[_currentIndex], //自动切换页面bottomNavigationBar: BottomNavigationBar(type: BottomNavigationBarType.fixed,currentIndex: _currentIndex,fixedColor: Colors.blue,onTap: (value) {setState(() {_currentIndex = value;});},items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.message), label: "消息"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),BottomNavigationBarItem(icon: Icon(Icons.people), label: "用户")],),floatingActionButton: Container(height: 60,width: 60,padding: const EdgeInsets.all(4),margin: const EdgeInsets.only(top: 4),decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(30)),child: FloatingActionButton(shape: const CircleBorder(),backgroundColor:_currentIndex == 2 ? Colors.yellowAccent : Colors.blueAccent,onPressed: () {setState(() {_currentIndex = 2;});},child: const Icon(Icons.add),),),floatingActionButtonLocation:FloatingActionButtonLocation.centerDocked, //浮动按钮位置);}
}

Scaffold属性:抽屉菜单Drawer

Scaffold 组件里面传入 drawer 参数可以定义左侧边栏,传入 endDrawer 可以定义右侧边栏。侧边栏默认是隐藏的,我们可以通过手指滑动显示侧边栏,也可以通过点击按钮显示侧边栏。

DrawerHeader

DrawerHeader 是侧边栏的头部,常见属性如下:

属性描述
decoration设置顶部背景颜色
child配置子元素
padding内边距
margin外边距

在上一节代码 tabs.dart 的基础上,我们来给页面添加侧边栏

class _TabsState extends State<Tabs> {int _currentIndex = 0; //当前选中索引final List<Widget> _pages = const [HomePage(),CategoryPage(),MessagePage(),SettingPage(),UserPage(),];Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("浮动按钮"),),//左侧边栏drawer: Drawer(child: Column(children: [DrawerHeader(decoration: const BoxDecoration(color: Colors.blueAccent,image: DecorationImage(image: NetworkImage("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/1.jpg"),fit: BoxFit.cover)),child: ListView(children: const [ListTile(leading: CircleAvatar(backgroundImage: NetworkImage("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/2.jpg"),),title: Text("嘻嘻",style: TextStyle(color: Colors.white,),),),ListTile(title: Text("Email: 123456@qq.com",style: TextStyle(color: Colors.white,),),),],),),const ListTile(leading: CircleAvatar(child: Icon(Icons.people)),title: Text("个人中心"),),const Divider(),const ListTile(leading: CircleAvatar(child: Icon(Icons.settings)),title: Text("系统设置"),)],),),//右侧侧边栏endDrawer: Drawer(child: Column(children: [DrawerHeader(decoration: const BoxDecoration(color: Colors.blueAccent,image: DecorationImage(image: NetworkImage("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/3.jpg"),fit: BoxFit.cover)),child: ListView(children: const [ListTile(leading: CircleAvatar(backgroundImage: NetworkImage("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/4.jpg"),),title: Text("嘻嘻",style: TextStyle(color: Colors.white,),),),ListTile(title: Text("Email: 123456@qq.com",style: TextStyle(color: Colors.white,),),),],),),const ListTile(leading: CircleAvatar(child: Icon(Icons.people)),title: Text("个人中心"),),const Divider(),const ListTile(leading: CircleAvatar(child: Icon(Icons.settings)),title: Text("系统设置"),)],),),body: _pages[_currentIndex], //自动切换页面bottomNavigationBar: BottomNavigationBar(type: BottomNavigationBarType.fixed,currentIndex: _currentIndex,fixedColor: Colors.blue,onTap: (value) {setState(() {_currentIndex = value;});},items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.message), label: "消息"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),BottomNavigationBarItem(icon: Icon(Icons.people), label: "用户")],),floatingActionButton: Container(height: 60,width: 60,padding: const EdgeInsets.all(4),margin: const EdgeInsets.only(top: 4),decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(30)),child: FloatingActionButton(shape: const CircleBorder(),backgroundColor:_currentIndex == 2 ? Colors.yellowAccent : Colors.blueAccent,onPressed: () {setState(() {_currentIndex = 2;});},child: const Icon(Icons.add),),),floatingActionButtonLocation:FloatingActionButtonLocation.centerDocked, //浮动按钮位置);}
}

左右侧边栏只是名称不同,其他组件的使用都是一致的

在这里插入图片描述

在这里插入图片描述

UserAccountsDrawerHeader

像前面这样我们自己写侧边栏的头部内容,还是比较麻烦的,而且样式也不好调整,为此 flutter 给我们提供了 UserAccountsDrawerHeader 组件,其常用属性如下:

属性描述
decoration设置顶部背景颜色
accountName账户名称
accountEmail账户邮箱
currentAccountPicture用户头像
otherAccountsPictures用来设置当前账户其他账户头像
margin外边距

接下来,我们用 来写一个侧边栏

//左侧边栏
drawer: Drawer(child: Column(children: [UserAccountsDrawerHeader(accountName: const Text("嘻嘻"),accountEmail: const Text("123456@qq.com"),currentAccountPicture: const CircleAvatar(backgroundImage: NetworkImage("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/1.jpg"),),decoration: const BoxDecoration(color: Colors.blue,image: DecorationImage(image: NetworkImage("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/2.jpg"),fit: BoxFit.cover),),otherAccountsPictures: [Image.network("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/3.jpg"),Image.network("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/4.jpg"),Image.network("https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/5.jpg"),],),const ListTile(leading: CircleAvatar(child: Icon(Icons.people)),title: Text("个人中心"),),const Divider(),const ListTile(leading: CircleAvatar(child: Icon(Icons.settings)),title: Text("系统设置"),)],),
),

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/15582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI菜鸟向前飞 — LangChain系列之十四 - Agent系列:从现象看机制(上篇)

上一篇介绍了Agent与LangGraph的基础技能Tool的必知必会 AI菜鸟向前飞 — LangChain系列之十三 - 关于Tool的必知必会 前面已经详细介绍了Promp、RAG&#xff0c;终于来到Agent系列&#xff08;别急后面还有LangGraph&#xff09;&#xff0c;大家可以先看下这张图&#xff1…

leetcode328. 奇偶链表,附详细解析和代码注释

leetcode328. 奇偶链表 给定单链表的头节点 head &#xff0c;将所有索引为奇数的节点和索引为偶数的节点分别组合在一起&#xff0c;然后返回重新排序的列表。 第一个节点的索引被认为是 奇数 &#xff0c; 第二个节点的索引为 偶数 &#xff0c;以此类推。 请注意&#xff0…

轻量级 K8S 环境 安装minikube

文章目录 操作系统DockerDocker CE 镜像源站使用官方安装脚本自动安装 &#xff08;仅适用于公网环境&#xff09;安装校验Docker代理docker permission denied while trying to connect to the Docker daemon socket minikubekubectl工具minikube dashboard参考资料 操作系统 …

Docker进入容器查看内容并从容器里拷贝文件到宿主机

工作中需要从docker正在运行的镜像中复制文件到宿主机&#xff0c;于是便将这个过程记录了下来。 &#xff08;1&#xff09;查看正在运行的容器 通过以下命令&#xff0c;可以查看正在运行的容器&#xff1a; docker ps &#xff08;2&#xff09;进入某个容器执行脚本 我…

react中子传父信息

思路是&#xff1a; 在父组件定义一个函数接受参数&#xff0c;接收的参数用于接收子组件的信息&#xff0c;把函数传给子组件&#xff0c;子组件调用父亲传来的函数并把要告诉父亲的话传到函数中&#xff0c;就实现了子传父消息 import { useState } from reactimport { use…

OpenWrt 安装Quagga 支持ospf Bgp等动态路由协议 软路由实测 系列四

1 Quagga 是一个路由软件套件, 提供 OSPFv2,OSPFv3,RIP v1 和 v2,RIPng 和 BGP-4 的实现. 2 web 登录安装 #或者ssh登录安装 opkg install quagga quagga-zebra quagga-bgpd quagga-watchquagga quagga-vtysh # reboot 3 ssh 登录 #重启服务 /etc/init.d/quagga restart #…

使用kubesphere部署微服务的时候,节点的镜像不是最新的导致部署到旧版本问题

我使用kubesphere部署微服务的时候&#xff0c;发现有很多次&#xff0c;我修改了配置文件&#xff0c;但是部署完才发现部署的是旧版本。 然后我查看了该微服务部署在哪个节点上&#xff1a; kubectl get pods --all-namespaces -o wide例如 gulimall-gateway 这个服务&…

韭菜的自我总结

韭菜的自我总结 股市技术面量价关系左侧右侧右侧技术左侧技术洗盘 韭菜的自我修养虚拟货币的启示韭菜的买入时机韭菜的心理压力成为优秀玩家的关键 股市技术面 技术面分析可以作为买卖时机判定的工具&#xff0c;但是投资还是需要基本面的分析作为支撑。也就是基本面选股&…

langchain进阶一:特殊的chain,轻松实现对话,与数据库操作,抽取数据,以及基于本地知识库的问答

特殊的chain langchain中的Chain有很多,能够轻松实现部分需求,极致简化代码,但是实现效果与模型智慧程度有关 会话链 效果与LLMChain大致相同 javascript 复制代码 from langchain.chains import ConversationChain from langchain_community.llms import OpenAI conversat…

Redis 实战 - 缓存异常及解决方案

文章目录 概述一、缓存穿透1.1 缓存穿透是什么1.2 解决方案 二、缓存击穿2.1 缓存击穿是什么2.2 解决方案 三、缓存雪崩3.1 缓存雪崩是什么3.2 解决方案 四、拓展4.1 缓存预热4.2 缓存降级 五、结语 把今天最好的表现当作明天最新的起点……&#xff0e;&#xff5e; 概述 在实…

LeetCode 第131场双周赛个人题解

100309. 求出出现两次数字的 XOR 值 原题链接 求出出现两次数字的 XOR 值 - 力扣 (LeetCode) 竞赛 思路分析 签到题&#xff0c;一次遍历 AC代码 class Solution:def duplicateNumbersXOR(self, nums: List[int]) -> int:cnt Counter(nums)res 0st set(nums)for x …

【大模型】Spring AI对接ChatGpt使用详解

目录 一、前言 二、spring ai介绍 2.1 什么是Spring AI 2.2 Spring AI 特点 2.3 Spring AI 为开发带来的便利 2.4 Spring AI应用领域 2.4.1 聊天模型 2.4.2 文本到图像模型 2.4.3 音频转文本 2.4.4 嵌入大模型使用 2.4.5 矢量数据库支持 2.4.6 用于数据工程ETL框架 …

2024-05-22 VS2022使用modules

点击 <C 语言编程核心突破> 快速C语言入门 VS2022使用modules 前言一、准备二、使用其一, 用VS installer 安装模块:第二个选项就是, 与你的代码一同编译std模块, 这个非常简单, 但是也有坑. 总结 前言 要解决问题: 使用VS2022开启modules. 想到的思路: 跟着官方文档整…

Java进阶学习笔记19——内部类

1、 内部类&#xff1a; 是类中五大成分之一&#xff08;成员变量、方法、构造函数、内部类、代码块&#xff09;&#xff0c;如果一个类定义在另一个 类的内部&#xff0c;这个类就是内部类。 场景&#xff1a;当一个类的内部&#xff0c;包含了一个完整的事物&#xff0c;且…

Android ART 虚拟机简析

源码基于&#xff1a;Android U 1. prop 名称选项名称heap 变量名称功能 dalvik.vm.heapstartsize MemoryInitialSize initial_heap_size_ 虚拟机在启动时&#xff0c;向系统申请的起始内存 dalvik.vm.heapgrowthlimit HeapGrowthLimit growth_limit_ 应用可使用的 max…

Scikit-Learn朴素贝叶斯

Scikit-Learn朴素贝叶斯 1、朴素贝叶斯1.1、贝叶斯分类1.2、贝叶斯定理1.3、贝叶斯定理的推导1.4、朴素贝叶斯及原理1.5、朴素贝叶斯的优缺点2、Scikit-Learn朴素贝叶斯2.1、Sklearn中的贝叶斯分类器2.2、Scikit-Learn朴素贝叶斯API2.3、Scikit-Learn朴素贝叶斯实践(新闻分类与…

爬山算法的详细介绍

目录 &#x1f349;概述 &#x1f349; 步骤 &#x1f349; 优缺点 &#x1f348;优点 &#x1f348;缺点 &#x1f348;应对策略 &#x1f349;示例 &#x1f348;旅行商问题 &#x1f34d;步骤 &#x1f34d;分解代码 &#x1f34e;包含头文件 &#x1f34e;定义函…

Cortex-M3的SysTick 定时器

目录 概述 1 SysTick 定时器 1.1 SysTick 定时器功能介绍 1.2 SysTick 定时器功能实现 1.3 SysTick在系统中的作用 2 SysTick应用的实例 2.1 建立异常服务例程 2.2 使能异常 2.3 闹钟功能 2.4 重定位向量表 2.5 消灭二次触发 3 SysTick在FreeRTOS中的应用 3.1 STM…

在docker中运行SLAM十四讲程序

《十四讲》的示例程序依赖比较多&#xff0c;而且系统有点旧。可以在容器中运行。 拉取镜像 docker pull ddhogan/slambook:v0.1这个docker对应的github&#xff1a;HomeLH/slambook2-docker 拉下来之后&#xff0c;假如是Windows系统&#xff0c;需要使用XLaunch用于提供X11…

面试大杂烩之kafka

面试这个领域最近环境不行&#xff0c;所以卷起来流量挺大 关于K8s 其实看我之前的博客&#xff0c;k8s刚有点苗头的时候我就研究过&#xff0c;然后工作的时候间接接触 也自己玩过 但是用的不多就忘记了&#xff0c;正苦于不知道写什么&#xff0c;水一篇 用来面试应该是够了…