Flutter 下拉组件(Drop Down)实现分页(Pagination)功能方案问询
Flutter 带分页功能的下拉选择组件实现方案
完全可以通过改造原生下拉组件实现需求,核心是配合分页参数、滚动监听和接口请求逻辑即可,不需要额外依赖复杂第三方库。
核心实现逻辑
- 维护四个核心状态变量:选项列表
options、当前分页偏移量currentOffset(初始值为0)、每页条数pageLimit(可自定义,比如10/20)、加载状态标记isLoading(防止重复请求)、是否还有更多数据标记hasMore(无更多数据时停止分页请求) - 首次进入页面时调用接口拉取第一页数据,传入
limit=pageLimit、offset=0 - 给下拉菜单的滚动列表添加滚动监听,当滚动位置距离底部小于指定阈值、且
isLoading为false、hasMore为true时,触发下一页数据请求 - 接口返回数据后,将新数据追加到已有选项列表末尾,更新
currentOffset = currentOffset + pageLimit,如果返回的新数据条数小于pageLimit,则将hasMore设为false,停止后续分页请求 - 加载过程中在下拉列表底部展示加载中占位,避免用户疑惑
核心代码示例
import 'package:flutter/material.dart'; class PaginationDropdown extends StatefulWidget { const PaginationDropdown({super.key}); @override State<PaginationDropdown> createState() => _PaginationDropdownState(); } class _PaginationDropdownState extends State<PaginationDropdown> { List<String> _options = []; String? _selectedOption; final int _pageLimit = 10; int _currentOffset = 0; bool _isLoading = false; bool _hasMore = true; final ScrollController _scrollController = ScrollController(); @override void initState() { super.initState(); // 首次加载第一页数据 _fetchOptions(); // 监听滚动事件触发分页 _scrollController.addListener(() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 200) { _fetchOptions(); } }); } Future<void> _fetchOptions() async { if (_isLoading || !_hasMore) return; setState(() { _isLoading = true; }); // 替换为你自己的业务API请求,传入limit和offset参数 // 示例代码模拟接口返回 await Future.delayed(const Duration(milliseconds: 800)); final List<String> newData = List.generate(_currentOffset >= 30 ? 5 : 10, (index) => "选项 ${_currentOffset + index + 1}"); if (newData.length < _pageLimit) { _hasMore = false; } _options.addAll(newData); _currentOffset += _pageLimit; setState(() { _isLoading = false; }); } @override Widget build(BuildContext context) { return DropdownButtonFormField<String>( decoration: const InputDecoration( labelText: "请选择选项", border: OutlineInputBorder(), contentPadding: EdgeInsets.symmetric(horizontal: 12), ), value: _selectedOption, menuMaxHeight: 300, scrollController: _scrollController, items: [ ..._options.map((option) => DropdownMenuItem( value: option, child: Text(option), )).toList(), // 加载中占位 if (_hasMore) const DropdownMenuItem( enabled: false, child: Center( child: Padding( padding: EdgeInsets.symmetric(vertical: 8), child: CircularProgressIndicator(strokeWidth: 2), ), ), ) ], onChanged: (value) { setState(() { _selectedOption = value; }); }, ); } @override void dispose() { _scrollController.dispose(); super.dispose(); } }
扩展说明
如果需要增加搜索过滤功能,只需要在用户输入搜索关键词时,重置_currentOffset为0、清空_options列表、重置_hasMore为true,再调用_fetchOptions传入搜索关键词参数即可。
内容的提问来源于stack exchange,提问作者Deepak Sharma
相关产品推荐
相关产品推荐

