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

Flutter中Expansion Tile溢出及按钮显示异常的解决咨询

解决方案:修复ExpansionTile溢出与底部按钮显示不全问题

问题根源

你当前的代码存在两个核心问题:

  1. 给SingleChildScrollView内部的Container设置了固定高度,当ExpansionTile展开后,内容高度超过固定值,导致底部按钮被挤出可视范围。
  2. 使用MainAxisAlignment.spaceBetween在固定高度容器中布局,内容变长时会将底部元素推到容器外部。

修改后的完整代码

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

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

  @override
  State<Address> createState() => _AddressState();
}

class _AddressState extends State<Address> {
  FocusNode addressText = FocusNode();
  bool _open = false;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        centerTitle: true,
        title: Container(
          width: 200,
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Expanded(
                child: LinearProgressIndicator(
                  value: 1,
                  backgroundColor: Color(0xD9D9D9D9),
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
                ),
              ),
              SizedBox(width: 7.0),
              Expanded(
                child: LinearProgressIndicator(
                  value: 1,
                  backgroundColor: Color(0xD9D9D9D9),
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
                ),
              ),
              SizedBox(width: 7.0),
              Expanded(
                child: LinearProgressIndicator(
                  value: 0.15,
                  backgroundColor: Color(0xD9D9D9D9),
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
                ),
              ),
            ],
          ),
        )
      ),
      body: Column(
        children: [
          // 可滚动的表单内容区域
          Expanded(
            child: SingleChildScrollView(
              padding: EdgeInsets.all(30.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text("Enter your address",style: TextStyle(fontSize: 22,fontFamily: "GraphikMedium"),),
                  SizedBox(height: 12,),
                  Text("Enter the street address of your primary residence. Please do not use a PO box or business address",
                    style: TextStyle(color: Colors.grey,fontSize: 16),),
                  SizedBox(height: 24,),
                  Text("Search for Address",style: TextStyle(fontSize: 16.0,fontFamily: "GraphikMedium",
                      color: addressText.hasFocus ? Colors.blue : Colors.black),
                  ),
                  SizedBox(height: 8.0,),
                  Focus(
                    onFocusChange: (focus){
                      setState(() {});
                    },
                    child: TextFormField(
                      focusNode: addressText,
                      decoration: InputDecoration(
                          enabledBorder: OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.grey),
                          ),
                          focusedBorder: OutlineInputBorder(
                              borderSide: BorderSide(color: Colors.blue)
                          ),
                          hintText: "Enter your address",
                          hintStyle: TextStyle(color: Colors.grey)
                      ),
                    ),
                  ),
                  SizedBox(height: 40,),
                  Theme(
                    data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
                    child: ListTileTheme(
                      contentPadding: EdgeInsets.all(0),
                      dense: true,
                      child: ExpansionTile(
                        title: Text("Enter Address Manually",style: TextStyle(fontFamily: "GraphikRegular",fontSize: 16.0),),
                        onExpansionChanged: (bool val) {
                          setState(() {
                            _open = val;
                          });
                        },
                        children: [
                          Container(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                SizedBox(height: 8.0,),
                                Text("Address line 1",style: TextStyle(fontFamily: "GraphikRegular",fontSize: 16.0),),
                                TextFormField(
                                  decoration: InputDecoration(
                                      enabledBorder: OutlineInputBorder(
                                          borderSide: BorderSide(color: Colors.grey)
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderSide: BorderSide(color: Colors.blue),
                                      )
                                  ),
                                ),
                                SizedBox(height: 8.0,),
                                Text("Address line 2 (optional)",style: TextStyle(fontFamily: "GraphikRegular",fontSize: 16.0),),
                                TextFormField(
                                  decoration: InputDecoration(
                                      enabledBorder: OutlineInputBorder(
                                          borderSide: BorderSide(color: Colors.grey)
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderSide: BorderSide(color: Colors.blue),
                                      )
                                  ),
                                ),
                                SizedBox(height: 8.0,),
                                Text("City",style: TextStyle(fontFamily: "GraphikRegular",fontSize: 16.0),),
                                TextFormField(
                                  decoration: InputDecoration(
                                      enabledBorder: OutlineInputBorder(
                                          borderSide: BorderSide(color: Colors.grey)
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderSide: BorderSide(color: Colors.blue),
                                      )
                                  ),
                                ),
                                SizedBox(height: 8.0,),
                                Text("City",style: TextStyle(fontFamily: "GraphikRegular",fontSize: 16.0),),
                                TextFormField(
                                  decoration: InputDecoration(
                                      enabledBorder: OutlineInputBorder(
                                          borderSide: BorderSide(color: Colors.grey)
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderSide: BorderSide(color: Colors.blue),
                                      )
                                  ),
                                ),
                              ],
                            ),
                          )
                        ],
                      ),
                    ),
                  )
                ],
              ),
            ),
          ),
          // 固定在底部的Continue按钮
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0),
            child: Container(
              width: MediaQuery.of(context).size.width,
              child: ElevatedButton(
                onPressed: (){
                  Navigator.pushNamed(context, '/user-purpose');
                },
                child: Text(
                  "Continue",
                  style: TextStyle(
                    fontSize: 14.0,
                    fontWeight: FontWeight.normal,
                    color: Colors.white,
                    fontFamily: "GraphikMedium",
                  ),
                ),
                style: ButtonStyle(
                    shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                        RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))
                    ),
                    minimumSize: MaterialStateProperty.all(Size.fromHeight(60.0)),
                    backgroundColor: MaterialStateProperty.all(Colors.blue),
                    shadowColor: MaterialStateProperty.all(Colors.transparent)
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

关键修改点

  1. 重构布局结构:将body改为Column,分为可滚动的内容区和固定的按钮区,彻底避免按钮被挤出的问题。
  2. 移除固定高度限制:删除了Container的固定height设置,让Expanded自动适配屏幕剩余空间,内容超出时自动滚动。
  3. 消除重复代码:去掉了原代码中重复的布局块,仅保留一套表单逻辑,通过ExpansionTile的状态控制展开/收起。
  4. 优化按钮定位:给底部按钮添加了上下内边距,确保按钮不会紧贴屏幕边缘,同时始终保持在可视区域底部。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:37:06