Flutter如何根据下拉列表选中项在容器中展示对应页面
Flutter 下拉列表选中项联动展示对应页面实现方案
你可以通过以下几步修改现有代码实现需求,效果和Android端Spinner+FrameLayout的组合完全一致:
- 第一步:在下拉选中回调中添加
setState触发状态刷新,你现有代码的onDropDownItemClick没有触发重绘,是选中后无响应的核心原因 - 第二步:预定义每个下拉选项对应的页面Widget,可以按索引匹配也可以通过键值对映射
- 第三步:在下拉组件下方添加占满剩余空间的容器,根据当前选中项动态渲染对应页面
修改后的完整代码如下:
import 'package:flutter/material.dart'; class DropDownWithiOsBackIcon extends StatefulWidget { @override _DropDownWithiOsBackIconState createState() => _DropDownWithiOsBackIconState(); } class _DropDownWithiOsBackIconState extends State<DropDownWithiOsBackIcon> { final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); bool _isBackPressedOrTouchedOutSide = false, _isDropDownOpened = false, _isPanDown = false, _navigateToPreviousScreenOnIOSBackPress = true; late List<String> _list; String _selectedItem = ''; // 定义每个选项对应的页面,和_list顺序一一对应 late List<Widget> _pageList; @override void initState() { _list = ["Abc", "DEF", "GHI", "JKL", "MNO", "PQR"]; _selectedItem = 'Select Item'; // 初始化对应页面,可替换为你自己的页面组件 _pageList = [ Center(child: Text('Abc 对应的页面内容', style: TextStyle(fontSize: 20))), Center(child: Text('DEF 对应的页面内容', style: TextStyle(fontSize: 20))), Center(child: Text('GHI 对应的页面内容', style: TextStyle(fontSize: 20))), Center(child: Text('JKL 对应的页面内容', style: TextStyle(fontSize: 20))), Center(child: Text('MNO 对应的页面内容', style: TextStyle(fontSize: 20))), Center(child: Text('PQR 对应的页面内容', style: TextStyle(fontSize: 20))), ]; super.initState(); } // 根据选中项获取对应页面 Widget _getCurrentPage() { if (_selectedItem == 'Select Item') { return Center(child: Text('请选择上方下拉选项', style: TextStyle(fontSize: 18, color: Colors.grey))); } int index = _list.indexOf(_selectedItem); return _pageList[index]; } @override Widget build(BuildContext context) { return GestureDetector( onTap: _removeFocus, onPanDown: (focus) { _isPanDown = true; _removeFocus(); }, child: Scaffold( backgroundColor: Colors.white, key: _scaffoldKey, appBar: PreferredSize( preferredSize: AppBar().preferredSize, child: SafeArea( child: PreferredSize( preferredSize: Size.fromHeight(100.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( width: 30, child: Container( margin: EdgeInsets.only( left: 8, ), child: IconButton( color: Colors.black, icon: Icon( Icons.arrow_back_ios, ), onPressed: _onWillPop, )), ), Container( margin: EdgeInsets.only( right: 60, ), child: Text('Awesome DropDown', style: TextStyle( color: Colors.black, fontSize: 22, fontWeight: FontWeight.bold)), ], )), ), ), // 把Column的mainAxisSize改成max,占满剩余高度 body: Column( children: [ Container( width: MediaQuery.of(context).size.width, margin: EdgeInsets.only(top: 15, left: 16, right: 20), child: AwesomeDropDown( isPanDown: _isPanDown, dropDownList: _list, isBackPressedOrTouchedOutSide: _isBackPressedOrTouchedOutSide, selectedItem: _selectedItem, onDropDownItemClick: (selectedItem) { // 添加setState触发重绘 setState(() { _selectedItem = selectedItem; }); }, dropStateChanged: (isOpened) { _isDropDownOpened = isOpened; if (!isOpened) { _isBackPressedOrTouchedOutSide = false; } }, ), ), // 添加类似FrameLayout的容器,占满剩余空间展示对应页面 Expanded( child: Container( width: double.infinity, margin: EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), ), child: _getCurrentPage(), ), ) ], ), ), ); } void _removeFocus() { if (_isDropDownOpened) { setState(() { _isBackPressedOrTouchedOutSide = true; }); _navigateToPreviousScreenOnIOSBackPress = false; } } Future<bool> _onWillPop() { if (_scaffoldKey.currentState!.isEndDrawerOpen) { Navigator.of(context).pop(); return Future.value(false); } else { if (_isDropDownOpened) { setState(() { _isBackPressedOrTouchedOutSide = true; }); FocusManager.instance.primaryFocus!.unfocus(); return Future.value(false); } else { if (_navigateToPreviousScreenOnIOSBackPress) { Navigator.of(context).pop(); return Future.value(true); } else { _navigateToPreviousScreenOnIOSBackPress = true; return Future.value(false); } } } } }
如果你的页面逻辑比较复杂,也可以把_pageList里的组件替换为你自己封装的独立Stateful/StatelessWidget即可。
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

