You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:24:01