如何将对话框放置在特定页面元素旁边,以便其位置在不同的屏幕尺寸上保持一致?

问题描述 投票:0回答:2

我正在尝试将对话框(例如工具提示、下拉列表或模式)放置在页面上特定元素的旁边。目标是保持对话框相对于元素的位置一致,无论屏幕大小或分辨率如何。

目前,当屏幕尺寸变化时,对话框的位置会发生变化,这会导致与其他元素错位或重叠。我需要一个解决方案,确保对话框保持锚定在目标元素旁边,而不会破坏不同设备上的布局或调整屏幕大小时。

问题: 如何将对话框放置在特定页面元素旁边,使其位置在不同的屏幕尺寸上保持一致?

这是我的代码:

  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

flutter dialog mobile-application showdialog
2个回答
0
投票

您可以使用 Stack 中的 Positioned 小部件,而不是依赖具有静态对齐值的 Align 小部件。这是修改后的代码

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"),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      );
    }

0
投票

您可以使用

CompositedTransformTarget
CompositedTransformFollower
或 OverLayPortal 为此。这是一个例子

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

  @override
  State<_SpecificPositionedDialog> createState() => _SpecificPositionedDialogState();
}

class _SpecificPositionedDialogState extends State<_SpecificPositionedDialog> {
  final LayerLink layerLink = LayerLink();

  bool showLink = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CompositedTransformTarget(
          link: layerLink,
          child: ElevatedButton(
            onPressed: () {
              showLink = !showLink;

              setState(() {});
            },
            child: const Text("Show"),
          ),
        ),
        if (showLink)
          CompositedTransformFollower(
            link: layerLink,
            showWhenUnlinked: false,
            targetAnchor: Alignment.bottomCenter,
            followerAnchor: Alignment.topCenter,
            child: Container(
              height: 200,
              width: 200,
              color: Colors.red.withOpacity(.2),
            ),
          ),
      ],
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.