当前位置: 首页 > news >正文

Flutter---个人信息(2)---实现修改昵称

效果图:点击修改昵称,修改后主页面和子页面都显示该名称

整体架构

HomePage (首页)
↓ (传递回调函数)
PersonInformationPage (个人信息页)
↓ (打开对话框)
ChangeNameDialog (修改名字弹窗)
↓ (用户确认)
数据回传

用户交互流程

用户点击昵称行 
→ 打开修改弹窗 
→ 输入新名字 
→ 点击确定 
→ 验证数据 
→ 更新状态 
→ 回调通知 
→ 关闭弹窗

关键代码

// 定义回调接口
final Function(String) onNameChanged;// 使用回调
widget.onNameChanged(newName);

状态管理三层架构​

// 第一层:弹窗内部状态
setState(() {_name = newName; // 更新个人信息页的显示
});// 第二层:回调父组件
widget.onNameChanged(newName); // 通知首页更新// 第三层:首页状态更新
onNameChanged: (newName) {setState(() {_homeName = newName; // 更新首页数据});
}

数据流

用户输入 ↓ 
TextField → TextEditingController ↓ 
数据验证 (trim + isNotEmpty) ↓ 
更新本地状态 (setState) ↓ 
回调父组件 (onNameChanged) ↓ 
更新首页状态 ↓ 
关闭弹窗 (Navigator.pop)

实现步骤

1.添加回调函数

final Function(String) onNameChanged; //1,添加回调函数

2.添加必须传入的名字回调函数

const PersonInformationPage({super.key,required this.onNameChanged});//2.添加必须传入的名字回调函数

3.添加文本控制器,控制用户输入的文本

final TextEditingController _nameController = TextEditingController();//3.添加文本控制器

4.初始化控制器

@overridevoid initState(){super.initState();_nameController.text = _name;}

5.清理控制器

//5.清理控制器@overridevoid dispose(){_nameController.dispose();super.dispose();}

6.在昵称这一行添加点击事件(修改名字的弹窗)

              onTap: () {// 6.增加修改名字的弹窗ChangeNameDialog();},

7.定义修改名字的弹窗

//7.定义修改名字的弹窗//========================修改名字的弹窗========================================//void ChangeNameDialog() {_nameController.text = _name; //设置当前名字到输入框showDialog(context: context,builder: (builder) {return Dialog(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26),),child: Container(width: 263,padding: EdgeInsets.only(top: 20,bottom: 29,left: 34,right: 34),decoration: BoxDecoration(color: Colors.white, //背景颜色borderRadius: BorderRadius.circular(26),),child: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text("修改昵称",style: const TextStyle(color: Colors.black,fontSize: 22,fontWeight: FontWeight.bold,),),],),SizedBox(height: 16),Container(padding: EdgeInsets.symmetric(horizontal: 12),decoration: BoxDecoration(color: Color(0xFFD8D8D8),//输入框颜色borderRadius: BorderRadius.circular(7),),child: TextField( //创建文本输入框组件controller: _nameController, //控制器:用于获取或者设置输入框文本内容style: TextStyle(color: Colors.white),decoration: InputDecoration(//hintText: "请输入",//提示性文字hintStyle: TextStyle(color: Colors.white54),border: InputBorder.none,),),),SizedBox(height: 20),Row(children: [//取消按钮Expanded(child: Container(height: 44, // 固定高度child: TextButton(onPressed: () => Navigator.pop(context),style: TextButton.styleFrom(backgroundColor: Color(0xFFD8D8D8),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26),),),child: Text("取消",style: TextStyle(color: Color(0xFF3D3D3D), fontSize: 16),),),),),SizedBox(width: 50),//确定按钮Expanded(child: Container(height: 44, // 固定高度child: TextButton(onPressed: () {//确定按钮具体的实现逻辑if(_nameController.text.trim().isNotEmpty){ //检查输入框内容是否非空String newName = _nameController.text.trim(); //获取输入框的文本内容setState(() {_name = newName; //当前页面状态,触发界面重绘});widget.onNameChanged(newName); //调用回调函数通知首页(home_page)Navigator.pop(context);//关闭对话框}},style: TextButton.styleFrom(backgroundColor: Color(0xff1F8FFF),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26),),),child: Text("确定",style: TextStyle(color: Colors.white, fontSize: 16),),),),),],)],),),);},).then((value) { //处理异步操作完成后的回调if(value != null && mounted) { //检查返回的结果不为空 && 检查当前组件是否还在挂载状态(避免在组件销毁后更新状态)Navigator.pop(context, value); //返回上一页并传递数据​​}});}

8.回到主页面(home_page)设置获取回调的名称且设置UI重建

//8.获取回调过来的昵称Navigator.push(context, MaterialPageRoute(builder: (context)=> PersonInformationPage(onNameChanged: (newName) {setState(() {_homeName = newName;//更新首页名字变量,引发UI重建});},)));

完整代码(实现修改名字的弹窗)

home_page.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter/person_information_page.dart';class HomePage extends StatefulWidget {const HomePage({super.key});@overrideState<StatefulWidget> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {var _homeGender = "男"; //性别var _homeName = "西西没烦恼"; //昵称var _homeBirthday = "2000-01-01"; // 出生年月var _homeHeight = "183"; // 身高// =======================计算具体年龄的方法=================================int get _age {try {//将字符串格式的生日(如 "2000-01-01")转换为 DateTime对象final birthDate = DateTime.parse(_homeBirthday);final now = DateTime.now(); //获取当前日期时间int age = now.year - birthDate.year; //计算基础年龄(虚岁)if (now.month < birthDate.month || (now.month == birthDate.month && now.day < birthDate.day)) { //判断是否已过生日(实岁)age--;}return age;} catch (e) {return 23; // 默认年龄}}//构建UI@overrideWidget build(BuildContext context) {return Scaffold(body: Container(height: double.infinity,padding: const EdgeInsets.all(16),// 主页背景颜色decoration: const BoxDecoration(gradient: LinearGradient(//渐变begin: Alignment.topCenter,end: Alignment.centerRight,colors: [Color(0xFF62F4F4),Color(0xFFF6F7F9),],),),child: SingleChildScrollView( //可滚动的页面physics: const ClampingScrollPhysics(),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [// 个人信息buildUserInfo(),const SizedBox(height: 25),],),),),);}//=======================个人信息的UI=====================================Widget buildUserInfo() {return Column(mainAxisAlignment: MainAxisAlignment.center,children: [const SizedBox(height: 96),// 头像:讲图片裁剪成圆形ClipOval(child: Image.asset("assets/images/apple.png",width: 90,height: 90,fit: BoxFit.cover,),),const SizedBox(height: 8),// 昵称Row(mainAxisAlignment: MainAxisAlignment.center,children: [GestureDetector(onTap: () {  //点击跳转个人信息详情页面//8.获取回调过来的昵称Navigator.push(context, MaterialPageRoute(builder: (context)=> PersonInformationPage(onNameChanged: (newName) {setState(() {_homeName = newName;//更新首页名字变量,引发UI重建});},)));},child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text(_homeName, // 名字style: TextStyle(color: const Color(0xFF3D3D3D),fontWeight: FontWeight.bold,fontSize: 24,),),const SizedBox(width: 10),Image.asset("assets/images/cherry.png",width: 20,height: 20,),],),),],),const SizedBox(height: 8),// 个人资料Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text(_homeGender, //性别style: TextStyle(color: const Color(0xFF3D3D3D), fontSize: 16),),// 竖线分隔符Container(width: 1,height: 16,margin: const EdgeInsets.symmetric(horizontal: 12),color: const Color(0xFFD8D8D8),),Text("${_age}岁", // 年龄style: TextStyle(color: const Color(0xFF3D3D3D), fontSize: 16),),// 竖线分隔符Container(width: 1,height: 16,margin: const EdgeInsets.symmetric(horizontal: 12),color: const Color(0xFFD8D8D8),),Text(_homeHeight,//身高style: TextStyle(color: const Color(0xFF3D3D3D), fontSize: 16),),Text("cm",style: TextStyle(color: const Color(0xFF3D3D3D), fontSize: 16),),],),],);}}

personal_information_page.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';class PersonInformationPage extends StatefulWidget {const PersonInformationPage({super.key,required this.onNameChanged});//2.添加必须传入的名字回调函数final Function(String) onNameChanged; //1,添加回调函数@overrideState<StatefulWidget> createState() => _PersonInformationPageState();
}class _PersonInformationPageState extends State<PersonInformationPage> {var _selectedGender = "男";//性别var _name = "西西没烦恼"; //昵称var _birthday = "2025-10-01";//初始日期var _height = "183"; //身高final TextEditingController _nameController = TextEditingController();//3.添加文本控制器//4.初始化控制器@overridevoid initState(){super.initState();_nameController.text = _name;}//5.清理控制器@overridevoid dispose(){_nameController.dispose();super.dispose();}// 构建UI@overrideWidget build(BuildContext context) {return Scaffold(body: Container(height: double.infinity,padding: const EdgeInsets.all(16),// 主页背景颜色decoration: const BoxDecoration(gradient: LinearGradient( //颜色渐变begin: Alignment.topCenter,end: Alignment.centerRight,colors: [Color(0xFF62F4F4),Color(0xFFF7F7F9),],),),child: SingleChildScrollView( //可滚动的页面child: Column(mainAxisAlignment: MainAxisAlignment.start,children: [const SizedBox(height: 96),// 头像:裁剪成圆形ClipOval(child: Image.asset("assets/images/apple.png",width: 90,height: 90,fit: BoxFit.cover,),),const SizedBox(height: 8),Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text("点击更换头像",style: TextStyle(color: const Color(0xFF3D3D3D),fontWeight: FontWeight.bold,fontSize: 24,),),const SizedBox(width: 10),],),const SizedBox(height: 8),Text("点击可更换个人信息",style: TextStyle(color: const Color(0xFF3D3D3D).withOpacity(0.6),fontSize: 12,),),const SizedBox(height: 38),// 个人信息列表buildListInformation(),],),),),);}//===========================个人信息列表=======================================//Widget buildListInformation() {return Padding(padding: const EdgeInsets.only(top: 10),child: Container(padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 31),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(30),),child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 昵称GestureDetector(onTap: () {// 6.增加修改名字的弹窗ChangeNameDialog();},child: Row(children: [Text("昵称",style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D)),),const Spacer(),Text(_name,style: TextStyle(color: Color(0xFF3D3D3D).withOpacity(0.6),fontSize: 14,),),const SizedBox(width: 6),Image.asset("assets/images/cherry.png",width: 30,height: 30,),],),),const SizedBox(height: 28),// 性别GestureDetector(onTap: () {},child: Row(children: [Text("性别",style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D)),),const Spacer(),Text(_selectedGender, // 显示当前选中性别style: TextStyle(color: Color(0xFF3D3D3D).withOpacity(0.6),fontSize: 14,),),const SizedBox(width: 6),Image.asset("assets/images/cherry.png",width: 30,height: 30,),],),),const SizedBox(height: 28),// 生日GestureDetector(onTap: () {},child: Row(children: [Text("生日",style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D)),),const Spacer(),Text(_birthday,style: TextStyle(color: Color(0xFF3D3D3D).withOpacity(0.6),fontSize: 14,),),const SizedBox(width: 6),Image.asset("assets/images/cherry.png",width: 30,height: 30,),],),),const SizedBox(height: 28),// 身高GestureDetector(onTap: () {},child: Row(children: [Text("身高",style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D)),),const Spacer(),Text(_height,style: TextStyle(color: Color(0xFF3D3D3D).withOpacity(0.6),fontSize: 14,),),Text("cm",style: TextStyle(color: Color(0xFF3D3D3D).withOpacity(0.6),fontSize: 14,),),const SizedBox(width: 6),Image.asset("assets/images/cherry.png",width: 30,height: 30,),],),),],),),);}//7.定义修改名字的弹窗//========================修改名字的弹窗========================================//void ChangeNameDialog() {_nameController.text = _name; //设置当前名字到输入框showDialog(context: context,builder: (builder) {return Dialog(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26),),child: Container(width: 263,padding: EdgeInsets.only(top: 20,bottom: 29,left: 34,right: 34),decoration: BoxDecoration(color: Colors.white, //背景颜色borderRadius: BorderRadius.circular(26),),child: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text("修改昵称",style: const TextStyle(color: Colors.black,fontSize: 22,fontWeight: FontWeight.bold,),),],),SizedBox(height: 16),Container(padding: EdgeInsets.symmetric(horizontal: 12),decoration: BoxDecoration(color: Color(0xFFD8D8D8),//输入框颜色borderRadius: BorderRadius.circular(7),),child: TextField( //创建文本输入框组件controller: _nameController, //控制器:用于获取或者设置输入框文本内容style: TextStyle(color: Colors.white),decoration: InputDecoration(//hintText: "请输入",//提示性文字hintStyle: TextStyle(color: Colors.white54),border: InputBorder.none,),),),SizedBox(height: 20),Row(children: [//取消按钮Expanded(child: Container(height: 44, // 固定高度child: TextButton(onPressed: () => Navigator.pop(context),style: TextButton.styleFrom(backgroundColor: Color(0xFFD8D8D8),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26),),),child: Text("取消",style: TextStyle(color: Color(0xFF3D3D3D), fontSize: 16),),),),),SizedBox(width: 50),//确定按钮Expanded(child: Container(height: 44, // 固定高度child: TextButton(onPressed: () {//确定按钮具体的实现逻辑if(_nameController.text.trim().isNotEmpty){ //检查输入框内容是否非空String newName = _nameController.text.trim(); //获取输入框的文本内容setState(() {_name = newName; //当前页面状态,触发界面重绘});widget.onNameChanged(newName); //调用回调函数通知首页(home_page)Navigator.pop(context);//关闭对话框}},style: TextButton.styleFrom(backgroundColor: Color(0xff1F8FFF),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26),),),child: Text("确定",style: TextStyle(color: Colors.white, fontSize: 16),),),),),],)],),),);},).then((value) { //处理异步操作完成后的回调if(value != null && mounted) { //检查返回的结果不为空 && 检查当前组件是否还在挂载状态(避免在组件销毁后更新状态)Navigator.pop(context, value); //返回上一页并传递数据​​}});}}

http://www.dtcms.com/a/550418.html

相关文章:

  • 深入解析 TCP 协议:从细节到实践的全方位解读
  • 题解:P12603 RuShiA(特殊情况下的 RSA 爆破)
  • 营销型网站建设和平台建设网站排行榜查询
  • 【代码】CF915E Physical Education Lessons [动态开点线段树]
  • 打造全新QAgent WeTest AI业务新上线
  • 虚拟主机怎么弄网站网站seo规范
  • 【技术经验】--如何和 Cursor 高效协作
  • 建网上商城的第三方网站哪个好17网站一起做网店潮汕
  • 關於概率部分,準備的三部曲
  • 新人做网站盈利北京小程序 app开发公司
  • 东莞网站设计智能 乐云践新网站开发 所有权
  • 在service方法中已经catch异常,Transactional失效怎么办
  • 服务平台网站设计门户网官网
  • 在线自助下单网站班级空间网站建设作用
  • Polarctf 写shell
  • 中建建筑网站机械设计师网课
  • 学习笔记一:基本术语
  • ssh网站开发的书籍织梦茶叶网站模板
  • 求网站建设详细过程网络规划设计师是高级职称吗
  • 【Linux权限 (二)】Linux权限机制深度解析:umask如何决定默认权限与粘滞位的妙用
  • 基于 Flask + APScheduler + MySQL 的自动报表系统设计
  • 建筑设计自学网站怎么开发一个自己的网站
  • go做网站网站建设优化东莞
  • AI智能座舱是什么?
  • 传奇手游网站大全9377网站建设哪便宜
  • 2023/12 JLPT听力原文 问题四
  • 域名备案时网站名称全国信息企业公示系统
  • Tokio的多线程调度器架构:深度解析与实践
  • Ubuntu(①shell脚本)
  • 个人婚礼网站模板网站建设 丽水