Flutter---个人信息(3)---实现修改性别

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

实现步骤

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("女");// 调用回调函数,传值回主页
                  },
                ),
              ],
            ),
          ),
        );
      },
    );
  }


}
相关推荐
西西学代码9 小时前
Flutter---ListTile列表项组件
flutter
西西学代码10 小时前
Flutter---个人信息(1)---实现简单的UI
开发语言·javascript·flutter
程序员老刘12 小时前
Dart宏被砍掉的真相:为什么Go、Python、Java等高级语言都拒绝宏?
flutter·编程语言·dart
月伤5916 小时前
Flutter中的Text换行问题
flutter
东哥很忙XH18 小时前
flutter开发的音乐搜索app
android·javascript·flutter
默默_david18 小时前
在Flutter中使用信号量解决异步冲突
flutter·dart
星释19 小时前
鸿蒙Flutter三方库适配指南: 05.使用Windows搭建开发环境
windows·flutter·harmonyos
倾云鹤20 小时前
搭建Flutter本地私有库
flutter
芝麻开门-新起点20 小时前
Flutter 网络通信协议:从原理到实战,选对协议让 APP 飞起来
flutter·ui·性能优化