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

Flutter如何获取自定义NumberSelector组件内部值并传值到新页面

解决Flutter组件状态值传递问题

方案一:状态提升(推荐)

把NumberSelector的状态(selectorValue)提升到父组件ExcersizeInput中,让父组件直接掌控数值,点击按钮时就能直接传递给下一个页面。

修改步骤:

  1. 将ExcersizeInput改为StatefulWidget,在其State类中维护cyclesVal变量。
  2. 给NumberSelector添加回调参数,内部数值变化时通知父组件更新。
  3. 让startTimer直接使用父组件的cyclesVal。

修改后的代码:

ExcersizeInput组件

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

  @override
  State<ExcersizeInput> createState() => _ExcersizeInputState();
}

class _ExcersizeInputState extends State<ExcersizeInput> {
  int cyclesVal = 1;

  void startTimer(BuildContext context) {
    Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => TimerPage(
            cycleCount: cyclesVal,
          ),
        ));
  }

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Column(
        children: [
          NumberSelector(
            title: "Cycles",
            initialValue: cyclesVal,
            onValueChanged: (newValue) {
              setState(() {
                cyclesVal = newValue;
              });
            },
          ),
        ],
      ),
      ElevatedButton.icon(
        onPressed: () => startTimer(context),
        label: const Text("Start"),
        icon: const Icon(Icons.start_outlined),
      )
    ]);
  }
}

NumberSelector组件

class NumberSelector extends StatefulWidget {
  final String title;
  final int initialValue;
  final Function(int) onValueChanged; // 添加回调函数

  const NumberSelector({
    super.key,
    required this.title,
    required this.initialValue,
    required this.onValueChanged,
  });

  @override
  State<NumberSelector> createState() => _NumberSelectorState();
}

class _NumberSelectorState extends State<NumberSelector> {
  late int selectorValue;

  @override
  void initState() {
    super.initState();
    selectorValue = widget.initialValue; // 从父组件初始化数值
  }

  void updateValue(bool ifAdd) { // 修正参数类型为bool
    setState(() {
      if (ifAdd) {
        if (selectorValue < 9999) {
          selectorValue++;
        }
      } else {
        if (selectorValue > 1) {
          selectorValue--;
        }
      }
      widget.onValueChanged(selectorValue); // 通知父组件数值更新
    });
  }

  @override
  Widget build(BuildContext context) {
    final ColorScheme colors = Theme.of(context).colorScheme;
    return Column(
      children: [
        Text(widget.title,
            style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
        Row(
          children: [
            IconButton(
              onPressed: () => updateValue(false),
              icon: const Icon(Icons.remove),
              // style: styleContainedButton, // 若未定义该变量可注释或补充
            ),
            Text(selectorValue.toString(),
                style: const TextStyle(fontSize: 16)),
            IconButton(
              onPressed: () => updateValue(true),
              icon: const Icon(Icons.add),
              // style: styleContainedButton,
            ),
          ],
        ),
      ],
    );
  }
}

方案二:使用GlobalKey(不推荐,破坏封装)

通过GlobalKey直接获取NumberSelector的State实例,读取内部的selectorValue。

修改步骤:

  1. 在ExcersizeInput的State类中定义GlobalKey。
  2. 给NumberSelector绑定该Key。
  3. 在startTimer中通过Key获取State并读取数值。

修改后的代码:

ExcersizeInput组件

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

  @override
  State<ExcersizeInput> createState() => _ExcersizeInputState();
}

class _ExcersizeInputState extends State<ExcersizeInput> {
  final GlobalKey<_NumberSelectorState> _selectorKey = GlobalKey();

  void startTimer(BuildContext context) {
    int cyclesVal = _selectorKey.currentState!.selectorValue;
    Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => TimerPage(
            cycleCount: cyclesVal,
          ),
        ));
  }

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Column(
        children: [
          NumberSelector(
            key: _selectorKey,
            title: "Cycles",
          ),
        ],
      ),
      ElevatedButton.icon(
        onPressed: () => startTimer(context),
        label: const Text("Start"),
        icon: const Icon(Icons.start_outlined),
      )
    ]);
  }
}

NumberSelector组件
需要将内部变量改为公开:

class _NumberSelectorState extends State<NumberSelector> {
  int selectorValue = 1; // 去掉下划线,改为公开变量

  // 其余代码不变
}

注意事项

  • 状态提升是Flutter官方推荐的方式,符合组件设计原则,耦合度低,便于维护。
  • GlobalKey方式虽简单,但会让父组件直接依赖子组件内部状态,破坏封装性,复杂项目中不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:51:31