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

Get.defaultDialog()弹出键盘时底部溢出问题求助

解决Get.defaultDialog键盘弹出时底部溢出的问题

核心问题分析

你当前的弹窗使用了固定高度的AnimatedContainer,当键盘弹出时屏幕可用空间缩小,固定高度容器无法自适应,直接导致内容溢出。同时内部ListView.builder虽设了shrinkWrap: true,但外层固定高度限制了它的自适应能力。

解决方案步骤

  • 移除AnimatedContainer的固定高度,让容器自动适配内容高度
  • 给外层SingleChildScrollView添加滚动物理属性,确保键盘弹出时内容可滚动
  • 给内部ListView.builder禁用滚动,避免内外滚动冲突
  • 限制弹窗最大高度(比如屏幕高度的70%),防止内容过多时铺满屏幕
  • 仅针对动态显示的TextFormField区域做高度动画,而非整个容器

修改后的完整代码

void cancelTask() {
  RxInt selectedreason = 0.obs;
  String cancelReason = kCancelReasonList[0].name;
  TextEditingController cancelReasonController = TextEditingController();
  Get.defaultDialog(
    title: kLanguageList!.value.clearTask,
    titleStyle: TextStyle(
      color: kBlack,
      fontSize: kTextScaleFactor * 18,
      fontWeight: FontWeight.bold,
    ),
    textConfirm: kLanguageList!.value.ok,
    confirmTextColor: kBlack,
    textCancel: kLanguageList!.value.cancel,
    cancelTextColor: kOrange,
    buttonColor: Colors.transparent,
    contentPadding: EdgeInsets.symmetric(
        vertical: kWidth * 0.02, horizontal: kWidth * 0.02),
    onConfirm: () {},
    // 限制弹窗最大高度为屏幕的70%,避免铺满屏幕
    content: ConstrainedBox(
      constraints: BoxConstraints(maxHeight: kHeight * 0.7),
      child: SingleChildScrollView(
        physics: const ClampingScrollPhysics(),
        child: Obx(
          () => AnimatedContainer(
            duration: selectedreason.value != 3
                ? const Duration(seconds: 1)
                : const Duration(milliseconds: 500),
            width: kWidth * 0.7,
            // 移除固定高度,让容器自适应内容
            child: Column(
              mainAxisSize: MainAxisSize.min, // 确保Column只占用必要高度
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                ListView.builder(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(), // 禁用内部滚动
                  itemCount: kCancelReasonList.length,
                  itemBuilder: (context, index) {
                    return RadioListTile(
                      toggleable: true,
                      title: CommonText(
                        text: kCancelReasonList[index].name.obs,
                        size: 1,
                        boldText: false,
                      ),
                      value: index,
                      groupValue: selectedreason.value,
                      onChanged: (int? reason) {
                        selectedreason.value = reason!;
                        cancelReason = kCancelReasonList[index].name;
                      },
                    );
                  },
                ),
                RadioListTile(
                  title: CommonText(
                    text: kLanguageList!.value.other.obs,
                    size: 1,
                    boldText: false,
                  ),
                  value: 3,
                  groupValue: selectedreason.value,
                  onChanged: (int? reason) {
                    selectedreason.value = reason!;
                    if (reason == 3) {
                      cancelReasonController.text = "";
                      cancelReason = "";
                    }
                  },
                ),
                Obx(() => AnimatedContainer(
                      duration: selectedreason.value == 3
                          ? const Duration(seconds: 1)
                          : const Duration(milliseconds: 500),
                      curve: Curves.fastOutSlowIn,
                      height: selectedreason.value == 3 ? kHeight * 0.085 : 0,
                      child: selectedreason.value == 3
                          ? CommonTextFormField(
                              controller: cancelReasonController,
                              onChanged: (reason) {
                                if (reason.isNotEmpty) {
                                  cancelReason = reason;
                                }
                              },
                              keyboardType: TextInputType.text,
                              focusBorderColor: kOrange,
                            )
                          : const SizedBox.shrink(),
                    ))
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

关键改动说明

  1. 移除固定高度:删除AnimatedContainer的height属性,通过Column(mainAxisSize: MainAxisSize.min)让布局自适应内容高度
  2. 添加滚动约束:用ConstrainedBox限制弹窗最大高度为屏幕70%,既避免铺满屏幕,又支持内容过多时滚动
  3. 解决滚动冲突:给ListView.builder添加NeverScrollableScrollPhysics(),让外层SingleChildScrollView统一处理滚动逻辑
  4. 保留动画逻辑:仅针对TextFormField区域做显示/隐藏动画,不影响整个弹窗的自适应高度特性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:10:34