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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 02:45:03