Search code examples
flutterdialogmobile-applicationshowdialog

How can I position a dialog next to specific page elements so that its placement remains consistent across different screen sizes?


I'm trying to position a dialog (e.g., a tooltip, dropdown, or modal) adjacent to a specific element on the page. The goal is to keep the dialog consistently positioned relative to the element, regardless of the screen size or resolution.

Currently, the dialog's position shifts when the screen size changes, which leads to misalignment or overlap with other elements. I need a solution that ensures the dialog stays anchored next to the target element without breaking the layout on different devices or when the screen is resized.

Question: How can I position a dialog next to specific page elements in a way that its placement remains consistent across different screen sizes?

This is my code:

  void onActionButtonPressed() {
    showDialog(
      barrierColor: Colors.transparent,
      context: pageContext,
      builder: (context) => Align(
        alignment: const Alignment(0.52, -0.65),
        child: Container(
          constraints: const BoxConstraints(maxWidth: 320, maxHeight: 235),
          padding: const EdgeInsets.fromLTRB(24, 24, 24, 32),
          decoration: BoxDecoration(
              color: CustomColors.surface,
              borderRadius: BorderRadius.circular(12),
              border: Border.all(
                width: 1,
                color: CustomColors.outline,
              )),
          child: const Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text("TEXT HERE"),
            ],
          ),
        ),
      ),
    );
  }

enter image description here


Solution

  • You can use the Positioned widget in the Stack instead of relying on the Align widget with static alignment values.Here is the modified code

    void onActionButtonPressed(BuildContext context) {
          RenderBox renderBox = context.findRenderObject() as RenderBox;
          Offset offset = renderBox.localToGlobal(Offset.zero);
          Size size = renderBox.size;
        
          showDialog(
            barrierColor: Colors.transparent,
            context: context,
            builder: (context) => Stack(
              children: [
                Positioned(
                  left: offset.dx,
                  top: offset.dy + size.height, 
                  child: Material(
                    color: Colors.transparent,
                    child: Container(
                      constraints: const BoxConstraints(maxWidth: 320, maxHeight: 235),
                      padding: const EdgeInsets.fromLTRB(24, 24, 24, 32),
                      decoration: BoxDecoration(
                        color: CustomColors.surface,
                        borderRadius: BorderRadius.circular(12),
                        border: Border.all(
                          width: 1,
                          color: CustomColors.outline,
                        ),
                      ),
                      child: const Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text("TEXT HERE"),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          );
        }