Flutter中Slidable结合ShowCase组件出现RenderBox布局渲染异常
Flutter Slidable与ShowCase结合报错RenderBox was not laid out的解决方法
问题场景
在Flutter开发中结合Slidable和ShowCase组件时,预期Slidable展开后ShowCase能展示预设引导内容,但运行时抛出如下断言错误:
======== Exception caught by rendering library ===================================================== The following assertion was thrown during paint(): RenderBox was not laid out: RenderClipRect#af542 'package:flutter/src/rendering/box.dart': Failed assertion: line 1972 pos 12: 'hasSize'
错误原因
Slidable默认处于收起状态,其endActionPane内的SlidableAction组件并未完成布局(无尺寸信息),而initState中直接调用startShowCase时,ShowCase尝试获取这些未布局组件的位置和尺寸,导致渲染断言失败。
解决方案
需先确保Slidable的ActionPane完全展开,待内部组件完成布局后,再启动ShowCase引导。通过SlidableController控制Slidable的展开状态,并在展开完成后延迟启动ShowCase即可解决。
修改后的组件代码
import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:loginmod/utils/app_colors.dart'; import 'package:showcaseview/showcaseview.dart'; class ShowCaseSalesTile extends StatefulWidget { final GlobalKey shareKey = GlobalKey(); final GlobalKey printKey = GlobalKey(); ShowCaseSalesTile({ Key? key, }) : super(key: key); @override State<ShowCaseSalesTile> createState() => _ShowCaseSalesTileState(); } class _ShowCaseSalesTileState extends State<ShowCaseSalesTile> { late SlidableController _slidableController; @override void initState() { _slidableController = SlidableController(); super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { // 先展开Slidable右侧操作面板 await _slidableController.openEndActionPane(); // 延迟确保组件完成布局后启动ShowCase Future.delayed(const Duration(milliseconds: 300), () { ShowCaseWidget.of(context) .startShowCase([widget.shareKey, widget.printKey]); }); }); } @override void dispose() { _slidableController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Slidable( controller: _slidableController, // 绑定控制器 endActionPane: ActionPane( motion: const ScrollMotion(), children: [ Showcase( key: widget.shareKey, title: "Share Data", description: "Share Bill With Others", child: SlidableAction( onPressed: (context) {}, backgroundColor: AppColors.secondaryColor, foregroundColor: Colors.white, icon: Icons.share, ), ), Showcase( key: widget.printKey, title: "Print Bill", description: "Print Bill", child: SlidableAction( onPressed: (context) {}, backgroundColor: AppColors.primaryColor, foregroundColor: Colors.white, icon: Icons.print, ), ), ], ), child: InkWell( onTap: () {}, child: Padding( padding: const EdgeInsets.all(8.0), child: ListTile(title: Text("Test 1"))), ), ); } }
关键说明
- 用
SlidableController精准控制Slidable的展开操作,确保操作面板先被打开。 - 延迟启动ShowCase是为了给组件足够的布局时间,避免再次触发未布局断言,延迟时间可根据实际场景调整。
- 在
dispose方法中销毁SlidableController,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Dev Adnani
相关产品推荐
相关产品推荐

