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

Flutter中PageBuilder内调用setState不生效问题如何解决?

问题根因

你在_TestPageState中调用setState只会触发当前页面的组件树重建,而通过PageRouteBuilder推出来的颜色选择器属于独立路由的组件树,默认不会跟随原页面的状态变更重新构建,因此修改actNum后只有原页面背景会更新,弹出的选择器页面会停留在初始状态。

解决方案

以下提供两种可行实现方案:

方案1:使用StatefulBuilder包裹弹出层内容

在PageRouteBuilder的pageBuilder中用StatefulBuilder包裹选择器内容,修改状态时同时触发弹出层自身的状态刷新,核心修改代码如下:

onTap: () {
  Navigator.of(context).push(PageRouteBuilder(
    opaque: false,
    maintainState: false,
    barrierDismissible: false,
    transitionDuration: Duration(milliseconds: 450),
    // 新增StatefulBuilder包裹页面内容
    pageBuilder: (BuildContext context, _, __) => StatefulBuilder(
      builder: (context, setStateDialog) {
        return Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          child: Stack(
            children: [
              Positioned(
                bottom: 100.0,
                child: Hero(
                  tag: "akcio",
                  child: GestureDetector(
                    onDoubleTap: () {
                      Navigator.of(context).pop();
                    },
                    onTap: () {
                      actNum = actNum == 1 ? 0 : 1;
                      // 同时触发原页面和弹出层的状态刷新
                      setState(() {});
                      setStateDialog(() {});
                    },
                    child: Container(
                      height: 100.0,
                      width: MediaQuery.of(context).size.width,
                      color: actNum == 1 ? Colors.greenAccent : Colors.white,
                      child: Text('Change color!'),
                    ),
                  ),
                ),
              )
            ],
          ),
        );
      },
    )
  ));
}

方案2:使用ValueNotifier做状态同步(更推荐)

将状态变量封装为ValueNotifier,两个页面同时监听状态变化,只要值更新两边会自动刷新UI,无需手动调用多个setState,完整修改代码如下:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:ui';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class CustomRectTween extends RectTween {
  final Rect? begin;
  final Rect? end;

  CustomRectTween({
    required this.begin,
    required this.end,
  }) : super(begin: begin, end: end);

  @override
  Rect lerp(double t) {
    final elasticCurveValue = Curves.easeOut.transform(t);
    double? xLeft = begin!.left;
    double yLeft = end!.left;
    double xRight = begin!.right;
    double yRight = end!.right;
    double xTop = begin!.top;
    double yTop = end!.top;
    double xBottom = begin!.bottom;
    double yBottom = end!.bottom;
    return Rect.fromLTRB(
      lerpDouble(xLeft, yLeft, elasticCurveValue)!,
      lerpDouble(xTop, yTop, elasticCurveValue)!,
      lerpDouble(xRight, yRight, elasticCurveValue)!,
      lerpDouble(xBottom, yBottom, elasticCurveValue)!,
    );
  }
}

class _TestPageState extends State<TestPage> {
  // 将actNum改为ValueNotifier
  final ValueNotifier<int> actNum = ValueNotifier(1);

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Stack(
          children: [
            // 用ValueListenableBuilder监听状态变化
            ValueListenableBuilder<int>(
              valueListenable: actNum,
              builder: (context, value, child) {
                return Container(
                  color: value == 1 ? Colors.greenAccent : Colors.white,
                  child: Hero(
                    tag: "akcio",
                    transitionOnUserGestures: true,
                    createRectTween: (begin, end) {
                      return CustomRectTween(begin: begin, end: end);
                    },
                    child: GestureDetector(
                      onTap: () {
                        Navigator.of(context).push(PageRouteBuilder(
                          opaque: false,
                          maintainState: false,
                          barrierDismissible: false,
                          transitionDuration: Duration(milliseconds: 450),
                          pageBuilder: (BuildContext context, _, __) {
                            return Container(
                              height: MediaQuery.of(context).size.height,
                              width: MediaQuery.of(context).size.width,
                              child: Stack(
                                children: [
                                  Positioned(
                                    bottom: 100.0,
                                    child: Hero(
                                      tag: "akcio",
                                      child: GestureDetector(
                                        onDoubleTap: () {
                                          Navigator.of(context).pop();
                                        },
                                        onTap: () {
                                          // 直接修改ValueNotifier的值即可,无需调用setState
                                          actNum.value = actNum.value == 1 ? 0 : 1;
                                        },
                                        // 弹出层也用ValueListenableBuilder监听状态
                                        child: ValueListenableBuilder<int>(
                                          valueListenable: actNum,
                                          builder: (context, dialogValue, child) {
                                            return Container(
                                              height: 100.0,
                                              width: MediaQuery.of(context).size.width,
                                              color: dialogValue == 1 ? Colors.greenAccent : Colors.white,
                                              child: Text('Change color!'),
                                            );
                                          },
                                        ),
                                      ),
                                    ),
                                  )
                                ],
                              ),
                            );
                          }
                        ));
                      },
                      child: Icon(
                        Icons.play_circle_fill,
                        color: Colors.black,
                        size: 75.0,
                      )
                    ),
                  ),
                );
              }
            )
          ],
        )
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:45:04