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


}
相关推荐
子春一1 小时前
Flutter for OpenHarmony:音律尺 - 基于Flutter的Web友好型节拍器开发与节奏可视化实现
前端·flutter
微祎_2 小时前
Flutter for OpenHarmony:单词迷宫一款基于 Flutter 构建的手势驱动字母拼词游戏,通过滑动手指连接字母路径来组成单词。
flutter·游戏
ujainu2 小时前
护眼又美观:Flutter + OpenHarmony 鸿蒙记事本一键切换夜间模式(四)
android·flutter·harmonyos
ujainu2 小时前
让笔记触手可及:为 Flutter + OpenHarmony 鸿蒙记事本添加实时搜索(二)
笔记·flutter·openharmony
一只大侠的侠2 小时前
Flutter开源鸿蒙跨平台训练营 Day 13从零开发注册页面
flutter·华为·harmonyos
一只大侠的侠2 小时前
Flutter开源鸿蒙跨平台训练营 Day19自定义 useFormik 实现高性能表单处理
flutter·开源·harmonyos
恋猫de小郭3 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
一只大侠的侠8 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
renke336412 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter
子春一14 小时前
Flutter for OpenHarmony:构建一个 Flutter 四色猜谜游戏,深入解析密码逻辑、反馈算法与经典益智游戏重构
算法·flutter·游戏