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

Flutter实现Instagram风格个人页GridView无限加载及整页滚动

问题解决方法

问题根源

你遇到的加载异常+滚动冲突问题来自两个核心原因:

  • 外层嵌套了SingleChildScrollView,内部GridView开启shrinkWrap: true时,GridView自身不会产生滚动区域,高度会自动适配所有子项总高度,所有滚动事件都被外层SingleChildScrollView消费,你绑定在GridView上的滚动监听器只能在首次初始化时触发一次,所以最多只能加载2页共30条数据。
  • 关闭shrinkWrap后GridView会独占滚动权限,就会出现只有GridView区域滚动、头部个人信息固定不动的问题,不符合Instagram个人页整体滚动的需求。

最优解决方案

推荐用CustomScrollView+Sliver系列组件实现,这是Flutter中实现整页滚动+网格列表无限加载的官方标准方案,完全符合你要的交互效果,具体修改步骤和代码如下:


1. 改造父页面AccountPage

将原有的SingleChildScrollView+Column结构替换为CustomScrollView,持有全局滚动控制器监听整页滚动事件:

import 'package:dresskip/model/user_model.dart';
import 'package:flutter/material.dart';
import 'itemSection_widget.dart';
import 'profileSection_widget.dart';
import '/assets/constants.dart' as constants;

class AccountPage extends StatefulWidget {
  const AccountPage({Key? key}) : super(key: key);

  @override
  State<AccountPage> createState() => _AccountPageState();
}

class _AccountPageState extends State<AccountPage> {
  final ScrollController _scrollController = ScrollController();
  final GlobalKey<_ItemSectionState> _itemSectionKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_scrollListener);
  }

  _scrollListener() {
    if (_scrollController.offset >=
            _scrollController.position.maxScrollExtent &&
        !_scrollController.position.outOfRange) {
      // 滚动到页面底部,触发加载更多
      _itemSectionKey.currentState?.loadMore();
    }
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          // 头部个人信息区域
          SliverToBoxAdapter(
            child: ProfileSection(
              description: getUserInformation().properties,
              onClicked: () async {},
            ),
          ),
          // 分割线
          const SliverToBoxAdapter(
            child: Divider(
              color: Color(constants.COLOR_BLUE_DRESSKIP),
              thickness: 2,
              indent: 50,
              endIndent: 50,
            ),
          ),
          // 网格列表区域
          ItemSection(key: _itemSectionKey),
        ],
      ),
    );
  }

  User getUserInformation() {
    User myUser = User(username: "test", email: "test@test.test", properties: [
      "22 yo\nFlexeur/Epicurien/Philanthrope\nJ'adore la vie\nEFREI Paris",
      "instagram_test",
      "facebook_test",
      "twitter"
    ]);
    return myUser;
  }
}

2. 改造ItemSection组件

移除自身的滚动控制器,将普通GridView替换为SliverGrid,关闭自身滚动能力:

import 'dart:developer';
import 'package:dresskip/model/item_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class ItemSection extends StatefulWidget {
  const ItemSection({Key? key}) : super(key: key);
  @override
  _ItemSectionState createState() => _ItemSectionState();
}

class _ItemSectionState extends State<ItemSection> {
  List<Item> items = [];
  bool isLoading = false;
  int pageCount = 1;

  @override
  void initState() {
    super.initState();
    // 加载第一页数据
    addItemsToList(1);
  }

  @override
  Widget build(BuildContext context) {
    return SliverGrid.count(
      crossAxisCount: 3,
      mainAxisSpacing: 0,
      children: items.map((value) {
        return Image.network(value.picture);
      }).toList(),
    );
  }

  // 对外暴露的加载更多方法
  void loadMore() {
    if (isLoading) return;
    setState(() {
      isLoading = true;
    });
    pageCount += 1;
    addItemsToList(pageCount);
  }

  addItemsToList(int page) {
    Item myItem = Item(
        name: "test",
        brand: "test",
        color: ["0xFF39BDC8", "0xFFdb8abc", ""],
        picture:
            "https://images.pexels.com/photos/9676177/pexels-photo-9676177.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
        solo: false,
        clean: true,
        type: "test");
    for (int i = (page * 15) - 15; i < page * 15; i++) {
      items.add(myItem);
    }
    setState(() {
      isLoading = false;
    });
  }
}

修正后的逻辑说明

  • 整个页面的滚动由CustomScrollView统一控制,头部个人信息和网格列表会一起滚动,完全匹配Instagram个人页的交互效果
  • 滚动监听绑定在全局滚动控制器上,每次滚动到页面底部都会触发下一页加载,不会再出现加载中断的问题
  • 修复了原有代码中addItemsToList方法未正确更新isLoading状态、传入的page参数未使用的小bug

内容的提问来源于stack exchange,提问作者FloconDavoine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:36:03