Flutter实现Column纵向排布及页面滚动 解决底部溢出问题
Flutter Column布局滚动失效、底部内容溢出修复
问题场景
需要实现纵向依次排列两个区块的页面,内容超出单屏高度时支持滚动浏览。直接使用SingleChildScrollView包裹整体内容后滚动不生效,同时出现底部内容溢出的报错。
问题效果如下:
可复现问题的原始代码:
import 'dart:async'; import 'package:flutter/material.dart'; void main() async { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( initialRoute: '/', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'aaaa'), ); } } class MyHomePage extends StatelessWidget { late String title; MyHomePage({required this.title}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(title), ), body: Column( children: [ Row(children: [ Expanded( flex: 1, child: Container( color: Color.fromARGB(255, 255, 252, 234), margin: const EdgeInsets.only(left: 20.0, top: 20.0, right: 20.0), child: SizedBox( height: 450, ), ), ), ]), Expanded( flex: 2, child: Column( children: [ Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), Text("Hello"), ], )), ], ), ); } }
问题根因
布局约束冲突导致:
SingleChildScrollView作为滚动容器,会给内部子节点传递无界的纵向高度约束,也就是允许子组件超过视口高度- 原代码给第二个区块套了
Expanded,这个组件的设计逻辑是在父组件给出的有界剩余空间内占满可用高度,碰到无界约束时无法正确计算自身高度,最终既无法触发滚动,还会出现内容溢出的报错。
修复方案
根据实际交互需求二选一即可:
方案1:整页统一滚动
如果需要上下两个区块跟着页面整体滚动,直接去掉第二个区块外层的Expanded,让第二个区块根据内容自适应高度,再用SingleChildScrollView包裹整个Column即可,修改后的body代码如下:
body: SingleChildScrollView( child: Column( children: [ Row(children: [ Expanded( flex: 1, child: Container( color: const Color.fromARGB(255, 255, 252, 234), margin: const EdgeInsets.only(left: 20.0, top: 20.0, right: 20.0), child: const SizedBox( height: 450, ), ), ), ]), // 移除Expanded,内容自适应高度 Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Column( children: List.generate(18, (index) => const Text("Hello")), ), ), ], ), )
方案2:上方区块固定,下方区块独立滚动
如果需要保留第一个区块固定在顶部、仅下方内容区滚动的交互,就保留外层Expanded,把滚动组件挪到第二个区块内部即可,修改后的body代码如下:
body: Column( children: [ Row(children: [ Expanded( flex: 1, child: Container( color: const Color.fromARGB(255, 255, 252, 234), margin: const EdgeInsets.only(left: 20.0, top: 20.0, right: 20.0), child: const SizedBox( height: 450, ), ), ), ]), Expanded( flex: 2, // 仅在内容区内部加滚动组件 child: SingleChildScrollView( child: Column( children: List.generate(18, (index) => const Text("Hello")), ), )), ], )
内容的提问来源于stack exchange,提问作者Dmitry Bubnenkov
相关产品推荐
相关产品推荐

