Flutter ExpansionPanel绑定bool值点击无法展开问题如何解决?
问题根源
你当前的theListings是_buildCategoryListings方法内的局部变量,每次组件触发重绘时,都会重新调用generateCategoryList()生成全新的MovieCategoryView实例集合,所有实例的isExpanded默认都是false。你在展开回调中修改的是本次build生成的临时数组属性,下次build又会被新生成的全为未展开状态的数组覆盖,所以看起来setState执行了但界面没有变化。
解决方案
把theListings提升为_MovieListingView State类的成员变量,仅在页面初始化时生成一次,后续修改直接操作这个持久化的数组即可,不需要每次build重新生成。
修改后的核心代码
class _MovieListingView extends State<MovieListingView> { // 把列表提升为成员变量 late List<MovieCategoryView> theListings; @override void initState() { super.initState(); // 初始化时只生成一次分类列表 theListings = generateCategoryList(); } @override Widget build(BuildContext context) { return SingleChildScrollView( physics: ScrollPhysics(), padding: EdgeInsets.all(5.0), child: _buildCategoryListings(), ); } List<MovieCategoryView> generateCategoryList() { List<MovieCategoryView> tempList = []; List<String> movieCategories = widget.movieList.Categories; movieCategories.forEach((category) { MovieCategoryView categoryView = MovieCategoryView( movieCategoryName: category.toString(), // 注意:原代码中StatefulWidget里的同名方法调用的是getMovieCardListByCategory,State里是getMenuItemCardListByCategory,按需统一即可 movieList: widget.movieList.getMenuItemCardListByCategory(category), isExpanded: false); tempList.add(categoryView); }); return tempList; } Widget _buildCategoryListings() { // 直接使用成员变量,不要再重新生成列表 return ExpansionPanelList( expansionCallback: (panelIndex, isExpanded) { setState(() { theListings[panelIndex].isExpanded = !isExpanded; }); }, children: theListings.map((MovieCategoryView movieCategoryView) { return ExpansionPanel( canTapOnHeader: true, headerBuilder: (BuildContext context, bool isExpanded) { return ListTile( title: Text(movieCategoryView.movieCategoryName), ); }, body: Column( children: movieCategoryView.movieList, ), isExpanded: movieCategoryView.isExpanded); }).toList(), ); } }
其他说明
这个场景完全不需要引入Provider,你担心的StatefulWidget可变变量规范问题不存在:State类本身就是用来管理可变的局部状态的,把和UI绑定的可变状态放在State的成员变量里是官方推荐的标准写法,你之前把变量放在StatefulWidget类里才不符合规范。
内容的提问来源于stack exchange,提问作者thebluechemist
相关产品推荐
相关产品推荐

