效果图:点击性别一行,可以更改性别信息



实现步骤
1.添加回调函数
Dart
final Function(String) onGenderChanged;//1,添加回调函数
2.添加必须传入的性别回调函数
Dart
const PersonInformationPage({super.key,required this.onNameChanged,required this.onGenderChanged});//2.添加必须传入的性别回调函数
3.在性别一行设置点击事件的提示框
Dart
onTap: () {
//3.设置修改性别的提示框
changeGenderDialog();
},
4.定义修改性别的弹窗
Dart
//4.定义修改性别的弹窗
//========================修改性别的弹窗========================================//
void changeGenderDialog() {
showDialog(
context: context,
builder: (context) {
return Dialog(
backgroundColor: Colors.white, //背景颜色
shape: RoundedRectangleBorder( //形状配置
borderRadius: BorderRadius.circular(26),
),
child: Container(
width: 250, // 自定义宽度
padding: EdgeInsets.all(16), // 内边距
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 男性选项
ListTile(
dense: true, //紧凑模式
title: Text("男", style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D))),
trailing: _selectedGender == "男" //只有选中"男",才显示男性行尾部图标(三元运算符)
? Image.asset("assets/images/cherry.png", width: 24, height: 24)
: null,
//点击事件
onTap: () {
Navigator.pop(context);//关闭对话框
setState(() {
_selectedGender = "男"; //更新性别变量值
});
widget.onGenderChanged("男");// 调用回调函数,传值回主页
},
),
// 女性选项
ListTile(
dense: true,//紧凑模式
title: Text("女", style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D))),
trailing: _selectedGender == "女" //只有选中"女",才显示女性行尾部图标
? Image.asset("assets/images/cherry.png", width: 24, height: 24)
: null,
onTap: () {
Navigator.pop(context);
setState(() {
_selectedGender = "女"; //更新性别变量值
});
widget.onGenderChanged("女");// 调用回调函数,传值回主页
},
),
],
),
),
);
},
);
}
5.回到主页面(home_page),获取回调函数的值,并更新UI
Dart
onGenderChanged: (newGender){
setState(() {
_homeGender = newGender; //5.接收子页面传过来的新性别,引发UI重建
});
},
ListTile组件的学习:Flutter---ListTile列表项组件-CSDN博客
代码实例
home_page.dart
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});
@override
State<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
@override
Widget 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重建
});
},
onGenderChanged: (newGender){
setState(() {
_homeGender = newGender; //5.接收子页面传过来的新性别,引发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
Dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class PersonInformationPage extends StatefulWidget {
const PersonInformationPage({super.key,required this.onNameChanged,required this.onGenderChanged});//2.添加必须传入的性别回调函数
final Function(String) onNameChanged;
final Function(String) onGenderChanged;//1,添加回调函数
@override
State<StatefulWidget> createState() => _PersonInformationPageState();
}
class _PersonInformationPageState extends State<PersonInformationPage> {
var _selectedGender = "男";//性别
var _name = "西西没烦恼"; //昵称
var _birthday = "2025-10-01";//初始日期
var _height = "183"; //身高
final TextEditingController _nameController = TextEditingController();
@override
void initState(){
super.initState();
_nameController.text = _name;
}
@override
void dispose(){
_nameController.dispose();
super.dispose();
}
// 构建UI
@override
Widget 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: () {
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: () {
//3.设置修改性别的提示框
changeGenderDialog();
},
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,
),
],
),
),
],
),
),
);
}
//========================修改名字的弹窗========================================//
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); //返回上一页并传递数据
}
});
}
//4.定义修改性别的弹窗
//========================修改性别的弹窗========================================//
void changeGenderDialog() {
showDialog(
context: context,
builder: (context) {
return Dialog(
backgroundColor: Colors.white, //背景颜色
shape: RoundedRectangleBorder( //形状配置
borderRadius: BorderRadius.circular(26),
),
child: Container(
width: 250, // 自定义宽度
padding: EdgeInsets.all(16), // 内边距
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 男性选项
ListTile(
dense: true, //紧凑模式
title: Text("男", style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D))),
trailing: _selectedGender == "男" //只有选中"男",才显示男性行尾部图标(三元运算符)
? Image.asset("assets/images/cherry.png", width: 24, height: 24)
: null,
//点击事件
onTap: () {
Navigator.pop(context);//关闭对话框
setState(() {
_selectedGender = "男"; //更新性别变量值
});
widget.onGenderChanged("男");// 调用回调函数,传值回主页
},
),
// 女性选项
ListTile(
dense: true,//紧凑模式
title: Text("女", style: TextStyle(fontSize: 16, color: Color(0xFF3D3D3D))),
trailing: _selectedGender == "女" //只有选中"女",才显示女性行尾部图标
? Image.asset("assets/images/cherry.png", width: 24, height: 24)
: null,
onTap: () {
Navigator.pop(context);
setState(() {
_selectedGender = "女"; //更新性别变量值
});
widget.onGenderChanged("女");// 调用回调函数,传值回主页
},
),
],
),
),
);
},
);
}
}