You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:如何将belt_controller的DropdownButton值传递到profile_reset_page

如何将DropdownButton的选中值从子组件传递到父组件?

我创建了belt_controller_page.dart文件,在profile_reset_page(资料修改页)中调用belt_controller()即可显示下拉按钮。现在需要把belt_controller里DropdownButton的选中值传递到profile_reset_page。我试过修改belt_controller的onChanged方法,实例化profile_reset_page并传值,同时给profile_reset_page添加必填参数,但未成功。


原代码

belt_controller组件代码

class belt_controller extends StatefulWidget {
  const belt_controller({super.key});

  @override
  State<belt_controller> createState() => _belt_controllerState();
}

class _belt_controllerState extends State<belt_controller> {

  ///Belt Controllers
  List<String> dropdownList = ['white', 'blue', 'purple', 'brown', 'black'];
  String selectedDropdown = 'white';


  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(25, 5, 25, 5),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey, width: 1),
          color: Colors.grey[200],
          borderRadius: BorderRadius.circular(10),
        ),
        child: DropdownButton(
          hint: const Text('belt'),
          value: selectedDropdown,
          focusColor: Colors.grey,
          dropdownColor: Colors.grey.shade400,
          icon: const Icon(Icons.arrow_drop_down),
          isExpanded: true,
          underline: const SizedBox(),
          style: const TextStyle(
            color: Colors.black,
            fontSize: 17,
          ),
          items: dropdownList.map((String item) {
            return DropdownMenuItem<String>(
              child: Text(item),
              value: item,
            );
          }).toList(),
          onChanged: (dynamic belt_value) {
            setState(() {
              selectedDropdown = belt_value;
              print(belt_value);
            });
          },
        ),
      ),
    );
  }
}

profile_reset_page页面代码

class profile_reset_page extends StatefulWidget {

  profile_reset_page({super.key});

  @override
  State<profile_reset_page> createState() => _profile_reset_pageState();
}

class _profile_reset_pageState extends State<profile_reset_page> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox(
        child: SafeArea(
          child: SingleChildScrollView(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  
                  belt_controller(),
                  
                  const SizedBox(height: 20,),
                  jiujitsuProfileButton(
                    text: 'Change',
                    TextColor: Colors.white,
                    BackgroundColor: Colors.red[300],
                    onTap: upDateUser,
                  ),
                ]
            ),
          ),
        ),
      ),
    );
  }
}

我的尝试(未成功)

修改belt_controller中的onChanged方法:

onChanged: (dynamic belt_value) {
  setState(() {
    selectedDropdown = belt_value;
    print(belt_value);
    profile_reset_page(belt_value:belt_value);
  });
},

同时给profile_reset_page添加final belt_value和必填参数,但没有效果。


正确解决方案

你之前的错误在于在子组件里实例化父组件,完全违背了组件通信逻辑。正确做法是通过回调函数将选中值从子组件传递到父组件:

步骤1:修改belt_controller组件,添加回调参数

class belt_controller extends StatefulWidget {
  // 定义回调函数,用于传递选中值
  final Function(String) onBeltSelected;
  // 可选:支持父组件传入初始选中值
  final String initialValue;

  const belt_controller({
    super.key,
    required this.onBeltSelected,
    this.initialValue = 'white',
  });

  @override
  State<belt_controller> createState() => _belt_controllerState();
}

class _belt_controllerState extends State<belt_controller> {
  late String selectedDropdown;

  List<String> dropdownList = ['white', 'blue', 'purple', 'brown', 'black'];

  @override
  void initState() {
    super.initState();
    // 用父组件传入的初始值初始化
    selectedDropdown = widget.initialValue;
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(25, 5, 25, 5),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey, width: 1),
          color: Colors.grey[200],
          borderRadius: BorderRadius.circular(10),
        ),
        child: DropdownButton<String>( // 明确类型,避免dynamic
          hint: const Text('belt'),
          value: selectedDropdown,
          focusColor: Colors.grey,
          dropdownColor: Colors.grey.shade400,
          icon: const Icon(Icons.arrow_drop_down),
          isExpanded: true,
          underline: const SizedBox(),
          style: const TextStyle(
            color: Colors.black,
            fontSize: 17,
          ),
          items: dropdownList.map((String item) {
            return DropdownMenuItem<String>(
              child: Text(item),
              value: item,
            );
          }).toList(),
          onChanged: (String? belt_value) {
            if (belt_value != null) {
              setState(() {
                selectedDropdown = belt_value;
              });
              // 调用回调函数,将选中值传给父组件
              widget.onBeltSelected(belt_value);
            }
          },
        ),
      ),
    );
  }
}

步骤2:修改profile_reset_page,接收子组件传递的值

class profile_reset_page extends StatefulWidget {
  const profile_reset_page({super.key});

  @override
  State<profile_reset_page> createState() => _profile_reset_pageState();
}

class _profile_reset_pageState extends State<profile_reset_page> {
  // 存储子组件传递过来的选中值
  String? selectedBelt;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox(
        child: SafeArea(
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                belt_controller(
                  // 传入回调函数,接收子组件的选中值
                  onBeltSelected: (value) {
                    setState(() {
                      selectedBelt = value;
                    });
                    print('父组件收到选中腰带:$value');
                  },
                  // 可选:设置初始选中值
                  initialValue: 'blue',
                ),
                const SizedBox(height: 20,),
                jiujitsuProfileButton(
                  text: 'Change',
                  TextColor: Colors.white,
                  BackgroundColor: Colors.red[300],
                  onTap: upDateUser,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  // 提交时可直接使用selectedBelt变量
  void upDateUser() {
    if (selectedBelt != null) {
      print('要提交的腰带值:$selectedBelt');
      // 执行更新用户资料的逻辑
    }
  }
}

说明

  • 回调函数是Flutter中子父组件通信的常用方式,子组件通过调用父组件传入的函数传递数据。
  • 禁止在子组件中实例化父组件,这会创建新的页面实例,而非更新当前页面状态。
  • 明确类型(如用String?代替dynamic)可提升代码可读性与安全性。

内容的提问来源于stack exchange,提问作者YUNN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:45:39