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

Flutter调用setState未更新AlertDialog内密码输入框可见性问题

问题原因
  • 你当前调用的setState是所属父页面的状态更新方法,而通过showGeneralDialog弹出的对话框是独立于父页面的新路由,父页面状态更新不会触发对话框内容重绘,只有重新打开对话框时才会加载最新的状态值。
  • 代码还存在变量名混用问题:图标显隐判断用的是passwordPortalVisible,但点击事件修改的是passwordVisible,两个变量不一致也会导致逻辑异常。
解决方案

核心是把对话框内容封装为独立的StatefulWidget,让对话框自己管理内部状态,点击切换可见性时调用对话框自身的setState就能实时刷新UI,修改后的可运行代码如下:

首先抽离独立的有状态密码对话框组件:

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

// 独立的密码输入对话框组件,自身持有状态
class PasswordInputDialog extends StatefulWidget {
  // 传入需要的外部参数
  final MaterialColor greyColor;
  final VoidCallback onConfirm;
  final TextEditingController textController;

  const PasswordInputDialog({
    super.key,
    required this.greyColor,
    required this.onConfirm,
    required this.textController,
  });

  @override
  State<PasswordInputDialog> createState() => _PasswordInputDialogState();
}

class _PasswordInputDialogState extends State<PasswordInputDialog> {
  // 对话框内部管理密码可见性状态
  bool _passwordVisible = false;

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      content: Wrap(
        alignment: WrapAlignment.center,
        children: [
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 10),
                child: TextField(
                  decoration: InputDecoration(
                    border: const OutlineInputBorder(
                      borderRadius: BorderRadius.all(Radius.circular(10)),
                    ),
                    hintText: '请输入密码',
                    suffixIconConstraints: const BoxConstraints.tightFor(
                      height: 50,
                      width: 50,
                    ),
                    suffixIcon: Padding(
                      padding: const EdgeInsets.only(top: 5),
                      child: SizedBox(
                        width: 24,
                        height: 24,
                        child: IconButton(
                          icon: _passwordVisible
                              ? SvgPicture.asset(
                                  "assets/svgs/icons/visibility_off.svg",
                                  fit: BoxFit.scaleDown,
                                  color: widget.greyColor.shade400,
                                )
                              : SvgPicture.asset(
                                  "assets/svgs/icons/visibility_on.svg",
                                  fit: BoxFit.scaleDown,
                                  color: widget.greyColor.shade400,
                                ),
                          onPressed: () {
                            // 调用对话框自身的setState实时刷新UI
                            setState(() {
                              _passwordVisible = !_passwordVisible;
                            });
                          },
                        ),
                      ),
                    ),
                  ),
                  controller: widget.textController,
                  keyboardType: TextInputType.number,
                  obscureText: !_passwordVisible,
                ),
              ),
            ],
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
            child: Row(
              children: [
                Expanded(
                  child: ElevatedButton(
                    onPressed: widget.onConfirm,
                    child: const Text('确定'),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

然后修改原有的对话框调用逻辑:

getConfirmationPortalKey() {
  return showGeneralDialog(
    transitionBuilder: (ctx, anim1, anim2, child) => BackdropFilter(
      filter: ImageFilter.blur(
        sigmaX: 4 * anim1.value,
        sigmaY: 4 * anim1.value,
      ),
      child: FadeTransition(
        opacity: anim1,
        child: child,
      ),
    ),
    context: context,
    barrierDismissible: true,
    barrierLabel: '',
    barrierColor: Colors.black26,
    transitionDuration: const Duration(milliseconds: 200),
    pageBuilder: (ctx, anim1, anim2) => PasswordInputDialog(
      greyColor: widget.colors.grey,
      textController: textEditingControllerKey,
      onConfirm: () {
        UserLogin user = UserLogin();
        // 此处补充确认按钮的其余逻辑
      },
    ),
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:12:03