使用 BlocListener 显示对话框

发布于 2025-01-11 22:25:41 字数 2335 浏览 1 评论 0原文

我有 2 个带有手势检测器的文本字段,点击手势检测器后,我使用 BlocListener 小部件打开一个 AlertDialog。

Widget _getSourceAndOriginTextField(String hintText, controller) {
    final portsCubit = BlocProvider.of<PortsCubit>(context);
    return TextFormField(
      controller: controller..text = "",
      readOnly: true,
      decoration: InputDecoration(
          suffixIcon: GestureDetector(
              onTap: () {
                portsCubit.getAllPorts();
              },
              child: BlocListener<PortsCubit, PortsState>(
                listenWhen: (previous, current) => previous != current,
                listener: (context, state) async {
                  if (state is PortsLoadedState) {
                    await showDialog(
                        context: context,
                        builder: (_) => BlocProvider.value(
                              value: portsCubit,
                              child: PortsDialog(state.portsList),
                            ));
                  }
                },
                child: SvgPicture.asset(
                  'assets/svg/chevron_down_icon.svg',
                  fit: BoxFit.scaleDown,
                  height: 10,
                  width: 18,
                ),
              )),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.0),
            borderSide: BorderSide(
              color: Colors.transparent,
              style: BorderStyle.solid,
              width: 1,
            ),
          ),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.0),
            borderSide: BorderSide.none,
          ),
          filled: true,
          contentPadding: EdgeInsets.all(8),
          hintText: hintText,
          hintStyle: AppStyle.hintStyle),
    );
  }

上面的方法返回一个 TextField,用于在表单内显示两个文本字段。

Form(
    children:[_getSourceAndOriginTextField('Origin',controller),
    SizedBox(height:10),
    _getSourceAndOriginTextField('Origin',controller)])

当我点击其中一个文本字段时,状态会发生变化,对话框会打开,但对话框会显示两次。我在这里缺少什么?

以下是供参考的图像,任何帮助将不胜感激。

表单内的文本字段

AlertDialog

I have 2 textFields that have a gesture detector and on tap of the gesture detector, I open an AlertDialog using the BlocListener widget.

Widget _getSourceAndOriginTextField(String hintText, controller) {
    final portsCubit = BlocProvider.of<PortsCubit>(context);
    return TextFormField(
      controller: controller..text = "",
      readOnly: true,
      decoration: InputDecoration(
          suffixIcon: GestureDetector(
              onTap: () {
                portsCubit.getAllPorts();
              },
              child: BlocListener<PortsCubit, PortsState>(
                listenWhen: (previous, current) => previous != current,
                listener: (context, state) async {
                  if (state is PortsLoadedState) {
                    await showDialog(
                        context: context,
                        builder: (_) => BlocProvider.value(
                              value: portsCubit,
                              child: PortsDialog(state.portsList),
                            ));
                  }
                },
                child: SvgPicture.asset(
                  'assets/svg/chevron_down_icon.svg',
                  fit: BoxFit.scaleDown,
                  height: 10,
                  width: 18,
                ),
              )),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.0),
            borderSide: BorderSide(
              color: Colors.transparent,
              style: BorderStyle.solid,
              width: 1,
            ),
          ),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.0),
            borderSide: BorderSide.none,
          ),
          filled: true,
          contentPadding: EdgeInsets.all(8),
          hintText: hintText,
          hintStyle: AppStyle.hintStyle),
    );
  }

This method above which returns a TextField is being used inside the form to display two textfields.

Form(
    children:[_getSourceAndOriginTextField('Origin',controller),
    SizedBox(height:10),
    _getSourceAndOriginTextField('Origin',controller)])

When I tap on one of the textfields the state changes and the dialog opens but the dialog is displayed twice. What am I missing here?

Following are the images for reference, any help will be appreciated.

TextField inside the form.

The AlertDialog

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

所谓喜欢 2025-01-18 22:25:41

我有 2 个文本字段

上面的方法返回一个 TextField,用于在表单内显示两个文本字段。

基本上可以解释你的问题。由于您执行了 _getSourceAndOriginTextField() 两次,因此您还创建了两次 BlocListener(...) 。因此,当 PortsCubit 状态更改为 PortsLoadedState 时,两个侦听器都会触发 showDialog 函数。

您可以做的就是提升 BlocListener 并用它包装 Form。这样,您将只有一个可以打开对话框的侦听器:

BlocListener<PortsCubit, PortsState>(
  listenWhen: (previous, current) => previous != current,
  listener: (context, state) async {
    if (state is PortsLoadedState) {
      await showDialog(
        context: context,
        builder: (_) => BlocProvider.value(
          value: portsCubit,
          child: PortsDialog(state.portsList),
      ));
  },
  child: Form(
    children:[_getSourceAndOriginTextField('Origin',controller),
    SizedBox(height:10),
    _getSourceAndOriginTextField('Origin',controller)]) 
},

I have 2 textFields

and

This method above which returns a TextField is being used inside the form to display two textfields.

basically explains your problem. Since you are executing _getSourceAndOriginTextField() twice, you also create the BlocListener<PortsCubit, PortsState>(...) twice. Thus, when the PortsCubit state changes to PortsLoadedState, both listeners trigger the showDialog function.

What you can do is lift the BlocListener and wrap the Form with it. This way you will have only a single listener that could open the dialog:

BlocListener<PortsCubit, PortsState>(
  listenWhen: (previous, current) => previous != current,
  listener: (context, state) async {
    if (state is PortsLoadedState) {
      await showDialog(
        context: context,
        builder: (_) => BlocProvider.value(
          value: portsCubit,
          child: PortsDialog(state.portsList),
      ));
  },
  child: Form(
    children:[_getSourceAndOriginTextField('Origin',controller),
    SizedBox(height:10),
    _getSourceAndOriginTextField('Origin',controller)]) 
},
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文