【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,一经查实,立即删除!

相关文章

AWS联网和内容分发之VPC

Amazon Virtual Private Cloud&#xff08;VPC&#xff09;是一项用于在AWS云中创建一个逻辑隔离的虚拟网络的服务&#xff0c;使用户能够在云中启动AWS资源&#xff08;例如EC2实例&#xff09;&#xff0c;并将其放置在自己定义的虚拟网络中。 Amazon VPC让您能够全面地控制…

AEE运行机制深入剖析——阅读笔记

AEE运行机制深入剖析——阅读笔记 在移动设备和嵌入式系统的开发中&#xff0c;应用执行环境&#xff08;Application Execution Environment&#xff0c;简称AEE&#xff09;起着至关重要的作用。AEE是操作系统层面的一个框架&#xff0c;负责管理应用程序的生命周期&#xf…

JVM性能调优:内存模型及垃圾收集算法

JVM内存结构 根据Java虚拟机规范&#xff0c;JVM内存主要划分为以下区域&#xff1a; 年轻代&#xff08;New Generation&#xff09; 包括Eden空间&#xff0c;用于存放新创建的对象。Survivor区由两个相同大小的Survivor1和Survivor2组成&#xff0c;用于存放经过初次垃圾回…

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…

Java的反射机制详解:动态操作类和对象

Java反射是一种强大的机制&#xff0c;允许程序在运行时查询和操作类、方法、接口等。这种能力使得Java应用可以在运行时动态地创建对象、调用方法和访问属性&#xff0c;极大地提升了程序的灵活性和可扩展性。本文将深入探讨Java反射的原理、核心API和实际应用场景&#xff0c…

Flutter 中的 CupertinoSlidingSegmentedControl 小部件:全面指南

Flutter 中的 CupertinoSlidingSegmentedControl 小部件&#xff1a;全面指南 在Flutter框架中&#xff0c;CupertinoSlidingSegmentedControl是一个用于创建类似iOS风格的滑动分段控制器的小部件。这种控制器通常用于允许用户在不同的视图或设置之间切换。本文将为您提供一个…

轻量级 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;进入某个容器执行脚本 我…

前端人员选择组件封装

功能&#xff1a; 人员选择&#xff0c;返回人员参数&#xff0c;以及人员参数id数组支持单选&#xff0c;多选人员支持重新选择回显上次选中人员 <!-- 弹窗 --><a-modal v-model"modalVisible" :footer"null" :bodyStyle"{ padding: 0 }&q…

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…

Spring Boot中如何实现定时任务?

在项目开发中&#xff0c;经常需要编写定时任务来实现一些功能&#xff1a; 定时备份数据库、定时发送邮件、定时清理数据、定时提醒或通知、信用卡每月还款提醒 未支付的订单15分钟之后自动取消、未确认收货的订单7天之后自动确认收货 定时任务的实现&#xff1a; Spring T…

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

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

YoloV8改进策略:Neck层改进、注意力改进|HCANet全局与局部的注意力模块CAFM|二次创新|即插即用

yolov9-c summary: 620 layers, 52330674 parameters, 0 gradients, 245.5 GFLOPsClass Images Instances P R mAP50 mAP50-95: 100%|██████████| 15/15 00:06all 230 1412 0.917 0.985 0.99 0.735…

实现自动化巡检多台交换机并将输出信息保存到文本文件中

为了实现自动化巡检多台交换机并将输出信息保存到文本文件中,可以扩展之前的 SSHInspectionTool 类,使其能够处理多台交换机的连接和命令执行。我们可以使用多线程来并行处理多个 SSH 连接,以提高效率。 目录 一、导入依赖包 二、编写Java类 (1)SSH.java (2)SSHIns…

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 …