Flutter报错:Column内使用SliverList引发RenderViewport类型不匹配
问题分析与解决方案
错误原因很明确:Sliver组件(如SliverList)只能在支持Sliver渲染的父组件中使用,比如CustomScrollView、NestedScrollView的slivers列表,或者Viewport组件。而你把SliverList放在了Column(属于RenderFlex类型组件)里,Column只能接受普通的RenderBox类型Widget,两者渲染对象类型不匹配,所以触发了RenderViewport expected a child of type RenderSliver but received a child of type RenderFlex错误。
下面给出两种可行的解决方案:
方案一:全Sliver结构(推荐,性能最优)
把原本Column里的内容全部转换成Sliver组件,直接放到CustomScrollView的slivers列表中,这样整个滚动体系是统一的,完全发挥Sliver组件的性能优势:
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Scaffold( body: CustomScrollView( slivers: [ // 标题部分转换成Sliver组件 SliverPadding( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 22), sliver: SliverToBoxAdapter( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Title", style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), ], ), ), ), // 用SliverConstrainedCrossAxis控制SliverList的高度 SliverConstrainedCrossAxis( maxCrossAxisExtent: 260, sliver: SliverList( delegate: SliverChildBuilderDelegate( childCount: 5, (context, index) { return Padding( padding: const EdgeInsets.all(8.0), child: Container( height: 80, width: 220, color: Colors.red, ), ); }, ), ), ), ], ), ); } }
方案二:保留Column结构,用ListView.builder替代
如果必须保留Column的布局结构,可以用ListView.builder代替SliverList,同时设置两个关键属性适配外层的CustomScrollView:
shrinkWrap: true:让ListView根据子项高度自适应,避免占用无限空间physics: const NeverScrollableScrollPhysics():禁用ListView自身滚动,让它跟着外层CustomScrollView一起滚动
修改后的代码:
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Scaffold( body: CustomScrollView( slivers: [ SliverToBoxAdapter(child: WidgetTest()), ], ), ); } } class WidgetTest extends StatefulWidget { const WidgetTest({Key? key}) : super(key: key); @override State<WidgetTest> createState() => _WidgetTestState(); } class _WidgetTestState extends State<WidgetTest> { @override Widget build(BuildContext context) { return Column( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 22), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Title", style: Theme.of(context).textTheme.headline1, ), ], ), ), SizedBox( height: 260, child: ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: 5, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(8.0), child: Container( height: 80, width: 220, color: Colors.red, ), ); }, ), ), ], ); } }
内容的提问来源于stack exchange,提问作者Hama Sabah
相关产品推荐
相关产品推荐

