Git Product home page Git Product logo

waterfall_flow's People

Contributors

alexv525 avatar meritozh avatar zmtzawqlp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

waterfall_flow's Issues

[Bug report] 下滑一段距离后再上滑,页面发生重新布局导致组件乱跳

Version

3.0.3

Platforms

Android

Device Model

Pixel 3a API 34

flutter info

[√] Flutter (Channel stable, 3.16.2, on Microsoft Windows [版本 10.0.22621.2715], locale zh-CN)
    • Flutter version 3.16.2 on channel stable at D:\AndroidDev\FlutterSDK\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9e1c857886 (6 days ago), 2023-11-30 11:51:18 -0600
    • Engine revision cf7a9d0800
    • Dart version 3.2.2
    • DevTools version 2.28.3

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at D:\AndroidDev\SDK
    • Platform android-34, build-tools 34.0.0
    • Java binary at: D:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)
    • All Android licenses accepted.

[X] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[X] Visual Studio - develop Windows apps
    X Visual Studio not installed; this is necessary to develop Windows apps.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components

[√] Android Studio (version 2022.3)
    • Android Studio at D:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)

[√] VS Code (version 1.84.2)
    • VS Code at C:\Users\handw\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension can be installed from:
       https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[√] Connected device (3 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 14 (API 34) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [版本 10.0.22621.2715]
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 119.0.2151.93

[!] Network resources                   
    X A cryptographic error occurred while checking "https://pub.dev/": Connection terminated during handshake
      You may be experiencing a man-in-the-middle attack, your network may be compromised, or you may have malware installed on your computer.
    X A network error occurred while checking "https://maven.google.com/": 信号灯超时时间已到


! Doctor found issues in 3 categories.

How to reproduce?

单个组件是一个套了好几层的 CachedNetworkImage,用一个 List.generate 生成 Waterflow 的 children 数组,下滑一段距离让上面的组件回收掉,然后再上滑让上面的组件重新加载,会出现重新布局、组件乱跳的情况

Logs

No response

Example code (optional)

class _ShortVideoWaterfallPageState extends State<ShortVideoWaterfallPage> {
  List<VideoDataModel> sttVideoList = [];
  ScrollController wfController = ScrollController();

  @override
  void initState() {
    super.initState();
    sttVideoList = widget.videoList;

    wfController.addListener(() {
      if (wfController.position.pixels ==
          wfController.position.maxScrollExtent) {
        widget.loadMoreContent(); // 到底部加载新内容
      }
    });
  }

  @override
  Widget build(BuildContext context) { // 构建 Widget
    return Padding(
      padding: const EdgeInsets.only(left: 5, right: 5),
      child: WaterfallFlow.count( // 瀑布流
        crossAxisCount: 2,
        controller: wfController,
        children: List.generate(sttVideoList.length,
            (index) => gridVideoBlock(sttVideoList[index])), // 用 List.generate 生成 children[],每个组件是 gridVideoBlock
      ),
    );
  }

  Widget gridVideoBlock(VideoDataModel video) { // 单个组件
    return Column(
      children: [
        GestureDetector(
          // ...
          child: Column(
            children: [
              Padding(
                // ...
                child: CachedNetworkImage( 
                  imageUrl: video.videoImageLink,
                  placeholder: (context, url) => const Center(
                    child: CircularProgressIndicator(),
                  ),
                  errorWidget: (context, url, error) => const Icon(Icons.error),
                ),
              ),
              // ...
            ],
          ),
        )
      ],
    );
  }
}

Contact

No response

关于列表 > TabBarView > WaterfallFlow的滚动异常

  • 表现一:TabBarView滚动时无法整体滚动
  • 表现二:如果把TabBarView的physics改为Never,则loadmore失效

请问这种带TabBarView的瀑布流如何做到整体滚动并刷新正常啊?

###6# 录屏

Simulator.Screen.Recording.-.iPhone.13.-.2022-05-31.at.10.36.20.2.mov

最简实现

import 'package:app/business/tuchong_item.dart';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:loading_more_list/loading_more_list.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:http_client_helper/http_client_helper.dart';
import 'package:loading_more_list_library/loading_more_list_library.dart';

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

  @override
  _ListWithTabState createState() => _ListWithTabState();
}

class _ListWithTabState extends State<ListWithTab> with SingleTickerProviderStateMixin {
  final List<Widget> myTabs = [
    Tab(text: 'tab1'),
    Tab(text: 'tab2'),
    Tab(text: 'tab3'),
  ];
  TabController? _tabController;
  List<int> dataSource = List.generate(100, (index) => index);
  int pageNumber = 1;

  @override
  void initState() {
    _tabController = TabController(length: 3, vsync: this);
    super.initState();
  }

  @override
  void dispose() {
    _tabController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LoadingMoreCustomScrollView(
        slivers: [
          SliverToBoxAdapter(child: Container(height: 300, color: Colors.red)),
          buildTabs(context),
          buildTabBarView(),
        ],
      ),
    );
  }

  SliverFillRemaining buildTabBarView() {
    return SliverFillRemaining(
      child: TabBarView(
        controller: _tabController,
        children: myTabs
            .map((e) => LoadingMoreList<TuChongItem>(
                  ListConfig<TuChongItem>(
                    itemBuilder: buildWaterfallFlowItem,
                    sourceList: TuChongRepository(),
                    padding: const EdgeInsets.all(5.0),
                    primary: false,
                    extendedListDelegate: const SliverWaterfallFlowDelegateWithMaxCrossAxisExtent(
                      maxCrossAxisExtent: 300,
                      crossAxisSpacing: 5,
                      mainAxisSpacing: 5,
                    ),
                    lastChildLayoutType: LastChildLayoutType.foot,
                  ),
                ))
            .toList(),
      ),
    );
  }

  SliverToBoxAdapter buildTabs(BuildContext context) {
    return SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.symmetric(vertical: 20),
        child: Align(
          alignment: Alignment.centerLeft,
          child: TabBar(
            isScrollable: true,
            padding: EdgeInsets.zero,
            controller: _tabController,
            tabs: myTabs,
            indicatorWeight: 3,
            indicatorColor: Theme.of(context).primaryColor,
            indicatorSize: TabBarIndicatorSize.label,
            labelColor: Theme.of(context).primaryColor,
            overlayColor: MaterialStateProperty.all(Colors.transparent),
          ),
        ),
      ),
    );
  }

  Widget buildWaterfallFlowItem(BuildContext c, TuChongItem item, int index) {
    return AspectRatio(
      aspectRatio: item.imageSize.width / item.imageSize.height,
      child: ExtendedImage.network(
        item.imageUrl,
        shape: BoxShape.rectangle,
        //clearMemoryCacheWhenDispose: true,
        border: Border.all(color: Colors.grey.withOpacity(0.4), width: 1.0),
        borderRadius: const BorderRadius.all(
          Radius.circular(10.0),
        ),
        loadStateChanged: (ExtendedImageState value) {
          if (value.extendedImageLoadState == LoadState.loading) {
            Widget loadingWidget = Container(
              alignment: Alignment.center,
              color: Colors.grey.withOpacity(0.8),
              child: CircularProgressIndicator(
                strokeWidth: 2.0,
                valueColor: AlwaysStoppedAnimation<Color>(Theme.of(c).primaryColor),
              ),
            );
            return loadingWidget;
          } else if (value.extendedImageLoadState == LoadState.completed) {
            item.imageRawSize = Size(value.extendedImageInfo!.image.width.toDouble(), value.extendedImageInfo!.image.height.toDouble());
          }
          return null;
        },
      ),
    );
  }
}

class TuChongRepository extends LoadingMoreBase<TuChongItem> {
  TuChongRepository({this.maxLength = 40});

  int _pageIndex = 1;
  bool _hasMore = true;
  bool forceRefresh = false;

  @override
  bool get hasMore => (_hasMore && length < maxLength) || forceRefresh;
  final int maxLength;

  @override
  Future<bool> refresh([bool notifyStateChanged = false]) async {
    _hasMore = true;
    _pageIndex = 1;
    //force to refresh list when you don't want clear list before request
    //for the case, if your list already has 20 items.
    forceRefresh = !notifyStateChanged;
    final bool result = await super.refresh(notifyStateChanged);
    forceRefresh = false;
    return result;
  }

  @override
  Future<bool> loadData([bool isloadMoreAction = false]) async {
    String url = '';
    if (isEmpty) {
      url = 'https://api.tuchong.com/feed-app';
    } else {
      final int? lastPostId = this[length - 1].postId;
      url = 'https://api.tuchong.com/feed-app?post_id=$lastPostId&page=$_pageIndex&type=loadmore';
    }
    bool isSuccess = false;
    try {
      //to show loading more clearly, in your app,remove this
      // await Future.delayed(const Duration(milliseconds: 500));
      List<TuChongItem>? feedList;
      final Response result = await HttpClientHelper.get(Uri.parse(url)) as Response;
      feedList = TuChongSource.fromJson(json.decode(result.body) as Map<String, dynamic>).feedList;

      if (_pageIndex == 1) {
        clear();
      }

      for (final TuChongItem item in feedList!) {
        if (item.hasImage && !contains(item) && hasMore) {
          add(item);
        }
      }
      _hasMore = feedList.isNotEmpty;
      _pageIndex++;
      isSuccess = true;
    } catch (exception, stack) {
      isSuccess = false;
      print(exception);
      print(stack);
    }
    return isSuccess;
  }
}

滚动冲突问题

c5ee86f12585396303ade47720be5d9d.mp4

大佬又遇到这个问题吗?
就是waterfall_flow和extended_nested_scroll_view一起使用再往上滚动的时候可能会出现无法滚上去(或者不流畅)的BUG

报错The getter 'parentData' was called on null

不知道什么原因引起的
image

导致第一行最后一个item下陷一个位置
IMG_20200602_072748

日志:

The following NoSuchMethodError was thrown during performLayout():
The getter 'parentData' was called on null.
Receiver: null
Tried calling: parentData

The relevant error-causing widget was: 
  LoadingMoreSliverList<GoodsItem> file:///C:/Users/lvccz/AndroidStudioProjects/demo1/lib/pages/index_page/index_home.dart:149:12
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1      CrossAxisItems.insertLeading (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:569:48)
#2      RenderSliverWaterfallFlow.performLayout (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:199:28)
#3      RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
#4      RenderSliverEdgeInsetsPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:134:11)
...
The following RenderObject was being processed when the exception was fired: RenderSliverWaterfallFlow#aacb0 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
...  needs compositing
...  parentData: paintOffset=Offset(13.6, 0.0) (can use size)
...  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.forward, scrollOffset: 522.5, remainingPaintExtent: 768.9, crossAxisExtent: 365.5, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 768.9, remainingCacheExtent: 1268.9 cacheOrigin: -250.0 )
...  geometry: SliverGeometry(scrollExtent: 8346.8, paintExtent: 768.9, maxPaintExtent: 8346.8, hasVisualOverflow: true, cacheExtent: 1268.9)
...    scrollExtent: 8346.8
...    paintExtent: 768.9
...    maxPaintExtent: 8346.8
...    hasVisualOverflow: true
...    cacheExtent: 1268.9
...  currently live children: 0 to 9
RenderObject: RenderSliverWaterfallFlow#aacb0 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
  needs compositing
  parentData: paintOffset=Offset(13.6, 0.0) (can use size)
  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.forward, scrollOffset: 522.5, remainingPaintExtent: 768.9, crossAxisExtent: 365.5, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 768.9, remainingCacheExtent: 1268.9 cacheOrigin: -250.0 )
  geometry: SliverGeometry(scrollExtent: 8346.8, paintExtent: 768.9, maxPaintExtent: 8346.8, hasVisualOverflow: true, cacheExtent: 1268.9)
    scrollExtent: 8346.8
    paintExtent: 768.9
    maxPaintExtent: 8346.8
    hasVisualOverflow: true
    cacheExtent: 1268.9
  currently live children: 0 to 9
...  child with index 0: RenderIndexedSemantics#51a2e relayoutBoundary=up3 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: crossAxisIndex=0;crossAxisOffset=0.0;trailingLayoutOffset=316.77886977886976; index=0; layoutOffset=-16.9 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 333.7)
...    index: 0
...    child: RenderRepaintBoundary#ab28e relayoutBoundary=up4 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      size: Size(175.7, 333.7)
...      usefulness ratio: no metrics collected yet (never painted)
...      child: RenderSemanticsAnnotations#b7eb5 relayoutBoundary=up5 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 333.7)
...        child: RenderMouseRegion#9e5e6 relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 333.7)
...          listeners: enter, exit
...  child with index 1: RenderIndexedSemantics#ef0b5 relayoutBoundary=up3 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: crossAxisIndex=1;crossAxisOffset=189.77886977886982;trailingLayoutOffset=315.8550368550368; index=1; layoutOffset=-16.9 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 332.8)
...    index: 1
...    child: RenderRepaintBoundary#fefb4 relayoutBoundary=up4 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      size: Size(175.7, 332.8)
...      usefulness ratio: no metrics collected yet (never painted)
...      child: RenderSemanticsAnnotations#b7613 relayoutBoundary=up5 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 332.8)
...        child: RenderMouseRegion#93d8d relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 332.8)
...          listeners: enter, exit
...  child with index 2: RenderIndexedSemantics#6341c relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=1;crossAxisOffset=189.77886977886982;trailingLayoutOffset=646.2702702702702; index=2; layoutOffset=329.5 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 2
...    child: RenderRepaintBoundary#4ffd8 relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#efcd0
...        offset: Offset(203.4, -284.6)
...      size: Size(175.7, 316.8)
...      metrics: 99.6% useful (2 bad vs 475 good)
...      diagnosis: this is an outstandingly useful repaint boundary and should definitely be kept
...      child: RenderSemanticsAnnotations#ff3d2 relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#6c37d relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
...  child with index 3: RenderIndexedSemantics#00e2f relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=0;crossAxisOffset=0.0;trailingLayoutOffset=647.1941031941031; index=3; layoutOffset=330.4 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 3
...    child: RenderRepaintBoundary#dd151 relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#18673
...        offset: Offset(13.6, -283.7)
...      size: Size(175.7, 316.8)
...      metrics: 99.6% useful (2 bad vs 474 good)
...      diagnosis: this is an outstandingly useful repaint boundary and should definitely be kept
...      child: RenderSemanticsAnnotations#03a6d relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#694cc relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
...  child with index 4: RenderIndexedSemantics#e61b8 relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=1;crossAxisOffset=189.77886977886982;trailingLayoutOffset=976.6855036855036; index=4; layoutOffset=659.9 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 4
...    child: RenderRepaintBoundary#680a7 relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#acd76
...        offset: Offset(203.4, 45.8)
...      size: Size(175.7, 316.8)
...      metrics: 98.3% useful (3 bad vs 177 good)
...      diagnosis: this is an outstandingly useful repaint boundary and should definitely be kept
...      child: RenderSemanticsAnnotations#38e2f relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#2fe33 relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
...  child with index 5: RenderIndexedSemantics#51375 relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=0;crossAxisOffset=0.0;trailingLayoutOffset=977.6093366093365; index=5; layoutOffset=660.8 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 5
...    child: RenderRepaintBoundary#56717 relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#3c9b2
...        offset: Offset(13.6, 46.7)
...      size: Size(175.7, 316.8)
...      metrics: 98.3% useful (3 bad vs 175 good)
...      diagnosis: this is an outstandingly useful repaint boundary and should definitely be kept
...      child: RenderSemanticsAnnotations#28fa0 relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#bf370 relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
...  child with index 6: RenderIndexedSemantics#aa09b relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=1;crossAxisOffset=189.77886977886982;trailingLayoutOffset=1307.100737100737; index=6; layoutOffset=990.3 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 6
...    child: RenderRepaintBoundary#d6555 relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#8273a
...        offset: Offset(203.4, 376.2)
...      size: Size(175.7, 316.8)
...      metrics: 98.7% useful (1 bad vs 75 good)
...      diagnosis: this is an outstandingly useful repaint boundary and should definitely be kept
...      child: RenderSemanticsAnnotations#fb511 relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#85d40 relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
...  child with index 7: RenderIndexedSemantics#4c1ee relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=0;crossAxisOffset=0.0;trailingLayoutOffset=1308.02457002457; index=7; layoutOffset=991.2 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 7
...    child: RenderRepaintBoundary#6734c relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#a8f86
...        offset: Offset(13.6, 377.1)
...      size: Size(175.7, 316.8)
...      metrics: 98.7% useful (1 bad vs 75 good)
...      diagnosis: this is an outstandingly useful repaint boundary and should definitely be kept
...      child: RenderSemanticsAnnotations#a757a relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#6b9e8 relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
...  child with index 8: RenderIndexedSemantics#10f69 relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=1;crossAxisOffset=189.77886977886982;trailingLayoutOffset=1636.5921375921375; index=8; layoutOffset=1320.7 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 315.9)
...    index: 8
...    child: RenderRepaintBoundary#a713a relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#ac017
...        offset: Offset(203.4, 706.6)
...      size: Size(175.7, 315.9)
...      metrics: 80.0% useful (1 bad vs 4 good)
...      diagnosis: this is a useful repaint boundary and should be kept
...      child: RenderSemanticsAnnotations#d0c4e relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 315.9)
...        child: RenderMouseRegion#a5fb3 relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 315.9)
...          listeners: enter, exit
...  child with index 9: RenderIndexedSemantics#27f00 relayoutBoundary=up3
...    needs compositing
...    parentData: crossAxisIndex=0;crossAxisOffset=0.0;trailingLayoutOffset=1638.4398034398037; index=9; layoutOffset=1321.7 (can use size)
...    constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...    semantic boundary
...    size: Size(175.7, 316.8)
...    index: 9
...    child: RenderRepaintBoundary#de1e4 relayoutBoundary=up4
...      needs compositing
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...      layer: OffsetLayer#b5394
...        offset: Offset(13.6, 707.6)
...      size: Size(175.7, 316.8)
...      metrics: 80.0% useful (1 bad vs 4 good)
...      diagnosis: this is a useful repaint boundary and should be kept
...      child: RenderSemanticsAnnotations#8b50f relayoutBoundary=up5
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...        size: Size(175.7, 316.8)
...        child: RenderMouseRegion#d3951 relayoutBoundary=up6
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(w=175.7, 0.0<=h<=Infinity)
...          size: Size(175.7, 316.8)
...          listeners: enter, exit
════════════════════════════════════════════════════════════════════════════════════════════════════

这是我的瀑布流wiget

首页商品列表
  Widget _buildGoodsList() {
    return LoadingMoreSliverList(SliverListConfig<GoodsItem>(
      waterfallFlowDelegate: WaterfallFlowDelegate(
          crossAxisCount: 2, crossAxisSpacing: ScreenUtil().setHeight(50), mainAxisSpacing: ScreenUtil().setWidth(50)),
      itemBuilder: (context, item, index) {
        return WaterfallGoodsCard(item);
      },
      sourceList: indexGoodsRepository,
      padding: EdgeInsets.only(left: ScreenUtil().setWidth(50),right: ScreenUtil().setWidth(50)),
      lastChildLayoutType: LastChildLayoutType.foot,
      indicatorBuilder: (context, state) {
        return LoadingMoreListCostumIndicator(state, isSliver: true);
      },
//      collectGarbage: (List<int> indexes) {
//        indexes.forEach((index) {
//          final item = indexGoodsRepository[index];
//          final provider = ExtendedNetworkImageProvider(
//            item.mainPic,
//          );
//          provider.evict();
//        });
//      },
    ));
  }

和刷新组件 pull_to_refresh: ^2.0.0 有兼容问题 使用了closeToTrailing: false属性导致布局脱离

body: SmartRefresher(
          enablePullDown: true,
          enablePullUp: true,
          controller: RefreshController(),
          child:
          // ListView.builder(
          //     itemCount: 10,
          //     itemBuilder: (context, index) {
          //       return Text('${index}');
          //     })
          WaterfallFlow.builder(
              gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 1, closeToTrailing: true),
              itemCount: 10,
              itemBuilder: (context, index) {
                return Text('${index}');
              }),
          ),

布局错乱 不能正确触发下拉刷新和上拉加载

窗口大小改变时的性能问题

越滚到底部性能越差,似乎窗口大小改变会重建当前位置之前所有的组件
ListView 和 GridView 无此问题

以下演示运行于 Release 模式

bandicam.2022-08-25.09-54-07-979.mp4

flutter 2.0.6 bug

代码

/// 默认的商品列表
class DefaultProductList extends StatelessWidget {
  final List<Product> products;
  final Function(bool isSuccess, Product product)? addToWishlistHandle;

  const DefaultProductList({Key? key, required this.products, this.addToWishlistHandle})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('商品列表是否为空${products==null}');
    return SliverWaterfallFlow(
        delegate: SliverChildBuilderDelegate(_builder,childCount: 1),
        gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            mainAxisSpacing: kDefaultPaddin,
            crossAxisSpacing: kDefaultPaddin,
            viewportBuilder: ProductListLogic.to.inView,
            collectGarbage: (List<int> indexes) {
              indexes.forEach((index) {
                if (products.isNotEmpty && products[index].imageFeature != null) {
                  final provider = ExtendedNetworkImageProvider(
                    products[index].imageFeature!,
                  );
                  provider.evict();
                }
              });
            }));
  }

  /// 商品每个项目的布局
  Widget _builder(BuildContext contextm, int index) {
    return Container(child: Text('1111'),);
  }

报错信息

======== Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
Build scheduled during frame.

While the widget tree was being built, laid out, and painted, a new frame was scheduled to rebuild the widget tree.

This might be because setState() was called from a layout or paint callback. If a change is needed to the widget tree, it should be applied as the tree is being built. Scheduling a change for the subsequent frame instead results in an interface that lags behind by one frame. If this was done to make your build dependent on a size measured at layout time, consider using a LayoutBuilder, CustomSingleChildLayout, or CustomMultiChildLayout. If, on the other hand, the one frame delay is the desired effect, for example because this is an animation, consider scheduling the frame in a post-frame callback using SchedulerBinding.addPostFrameCallback or using an AnimationController to trigger the animation.

删除SliverWaterfallFlow这个组件后正常

scrolling a grid causes items to jump/re-shuffle

Hi and thanks for this useful plugin.

I am using the latest version as of 1st Nov 2020.,

I notice that when I show a mixture of TEXT and images approx 60 cells (30 text cells and 30 image cells of different sizes) and scroll through - the cells appear to jump from 1 side to the next - I am testing this on a live device and get this issue on ANDROID and iOS. Its as if each scroll gesture forces the rebuild of the grid and then the cells get re-shuffled.

I have tested using a normal gridView and do not get this behaviour.

When the grid cells are the same size - the issue does not appear . When we have different sized IMAGES - we get the issue.

The code I use is :


WaterfallFlow.custom(
        padding: EdgeInsets.all(10),
        gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
            crossAxisCount: crossAxis, crossAxisSpacing: 5, mainAxisSpacing: 5),
        childrenDelegate: SliverChildBuilderDelegate((context, index) {
          var model = items[index].item2;
          var comp = items[index].item1;

          if (model.pictureUrl == null) {
           /// Display a TEXT widget
            return Container(height: 100, width: 100, child: comp);
          } else {
          /// Display an Image widget
            return comp;
          }
        }, childCount: items.length),
      );

会偶现某一个item为空白的情况

Flutter doctor info:
[✓] Flutter (Channel unknown, v1.14.6, on Mac OS X 10.14.6 18G84, locale
zh-Hans-CN)
• Flutter version 1.14.6 at /Users/huangyumeng/flutter/sdk/flutter
• Framework revision fabeb2a16f (4 months ago), 2020-01-28 07:56:51 -0800
• Engine revision c4229bfbba
• Dart version 2.8.0 (build 2.8.0-dev.5.0 fc3af737c7)

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.0)
• Android SDK at /Users/huangyumeng/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling
support)
• Platform android-29, build-tools 29.0.0
• Java binary at: /Applications/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_212-release-1586-b4-5784211)
! Some Android licenses not accepted. To resolve this, run: flutter doctor
--android-licenses

[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.3.1, Build version 11C504
• CocoaPods version 1.7.4

[✓] Android Studio (version 3.6)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 45.1.1
• Dart plugin version 192.8052
• Java version OpenJDK Runtime Environment (build
1.8.0_212-release-1586-b4-5784211)

[✓] Connected device (1 available)
• Redmi Note 8 Pro • 192.168.1.53:5555 • android-arm64 • Android 9 (API 28)

! Doctor found issues in 1 category.

问题描述:
产品瀑布流默认为两列,会偶现第二列某一个区域为空白的情况,滑动后第二列整个消失,第一列的布局会挤在一起。布局代码:

SliverPadding(
          padding: EdgeInsets.all(kMomentWaterfallCrossAxisSpacing),
          sliver: SliverWaterfallFlow(
            gridDelegate: SliverWaterfallFlowDelegate(
                crossAxisCount: kMomentWaterfallCrossAxisCount,
                mainAxisSpacing: kMomentWaterfallMainAxisSpacing,
                crossAxisSpacing: kMomentWaterfallCrossAxisSpacing,
                lastChildLayoutTypeBuilder: (idx) {
                  return idx == _model.momentList.length
                      ? LastChildLayoutType.foot
                      : LastChildLayoutType.none;
                },
                viewportBuilder: (firstIdx, lastIdx) {},
                collectGarbage: (List<int> collectIdxList) {
                  for (int idx in collectIdxList) {
                    dataList[idx].evictImageInfo();
                  }
                }),
            delegate: SliverChildBuilderDelegate((context, idx) {
              return ItemTile();
            }, childCount: dataList.length),
          ),
        )

Bugly报错:
NoSuchMethodError: The getter 'parentData' was called on null. Receiver: null Tried calling: parentData

#0 CrossAxisItems.insertLeading (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:569)

#1 RenderSliverWaterfallFlow.performLayout (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:199)
#2 RenderObject.layout (package:flutter/src/rendering/object.dart:1767)
#3 RenderSliverEdgeInsetsPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:134)
#4 RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:373)
#5 RenderObject.layout (package:flutter/src/rendering/object.dart:1767)
#6 RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:452)
#7 RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1444)
#8 RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1353)
10 #9 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1628)
11 #10 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:888)
12 #11 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:401)
13 #12 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:797)
14 #13 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:283)
15 #14 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1109)
16 #15 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1048)
17 #16 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:964)
18 #17 _rootRun (dart:async/zone.dart:1126)
19 #18 _CustomZone.run (dart:async/zone.dart:1023)
20 #19 _CustomZone.runGuarded (dart:async/zone.dart:925)
21 #20 _invoke (dart:ui/hooks.dart:260)
22 #21 _drawFrame (dart:ui/hooks.dart:218)

SliverGrid example

I was searching for alternative for Staggered Grid View due to its performance issue and found this package...

thought to use it but not understood example...

I have a requirement to replace SliverStaggeredGrid.countBuilder() with CustomScrollView(). If possible can you share some sample code or share the document if already available....

瀑布流左右距屏幕边距如何设置

Container(
  padding: EdgeInsets.only(left: 10.0),
  child: SliverWaterfallFlow(
    gridDelegate:
        SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
      crossAxisCount: crossAxisCount,
      crossAxisSpacing: crossAxisSpacing,
      mainAxisSpacing: mainAxisSpacing,
    ),
    delegate: SliverChildBuilderDelegate(
        (BuildContext c, int index) {
      return Container(
        child: buildWaterfallFlowItem(
            c, records[index], index),
      );
    }, childCount: records.length),
  ),

如果在外面包一层Container 会报错

NoSuchMethodError: The getter 'height' was called on null. Receiver: null Tried calling: height

I know waterfall_flow widget extend sliver_multi_box_adaptor.dart.
I find error but can't reproduce it. see log:


#0 RenderSliverMultiBoxAdaptor.paintExtentOf (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:554)
--
2 #1 _CrossAxisChildrenData.insertLeading (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:911)
3 #2 RenderSliverWaterfallFlow.performLayout (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:447)
4 #3 RenderObject.layout (package:flutter/src/rendering/object.dart:1767)
5 #4 RenderSliverEdgeInsetsPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:135)
6 #5 <optimized out> (<optimized out>:375)
7 #6 RenderObject.layout (package:flutter/src/rendering/object.dart:1767)
8 #7 RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:452)
9 #8 RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1444)
10 #9 <optimized out> (<optimized out>:1353)
11 #10 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1630)
12 #11 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:887)
13 #12 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:402)
14 #13 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:884)
15 #14 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:284)
16 #15 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1113)
17 #16 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1052)
18 #17 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:968)
19 #18 _rootRun (dart:async/zone.dart:1184)
20 #19 _CustomZone.run (dart:async/zone.dart:1077)
21 #20 _CustomZone.runGuarded (dart:async/zone.dart:979)
22 #21 _invoke (dart:ui/hooks.dart:261)
23 #22 _drawFrame (dart:ui/hooks.dart:219)


flutter issue
Maybe how to avoid this error.

Then add judgment insertLeading Function like this

903      // This child is after the leadings.
904      if (leading == null || data.index > leading.index || child.size == null) {
905       return;
      }

Getter 'minTrailingIndex' was called on null

I have a SliverWaterfallFlowDelegateWithMaxCrossAxisExtent that creates a Waterfall grid of elements.

When the device is rotated from a longer list (portrait) to a shorter list (landscape), the bottom of the list goes empty and you have to scroll up to reach to latest items.

Reproduction:

  1. When the device starts is portrait, the list is rendered as a 1 item list in the cross axis
  2. Scroll to the bottom of list.
  3. Turn the device to landscape.

Expected:

  • The list rebuilds having 2 items in the cross axis and showing the latest 2 or 1 items

Happening:

  • The list rebuilds but the latest items are way up high in the list. You have to scroll up to get to the latest items.

Also, this error is thrown:

════════ Exception caught by rendering library ═════════════════════════════════
The following NoSuchMethodError was thrown during performLayout():
The getter 'minTrailingIndex' was called on null.
Receiver: null
Tried calling: minTrailingIndex

The relevant error-causing widget was
SliverWaterfallFlow
 lib/…/components/flageventlistscaffold.dart
When the exception was thrown, this was the stack
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1      RenderSliverWaterfallFlow.performLayout
 package:waterfall_flow/…/rendering/sliver_waterfall_flow.dart
#2      RenderObject.layout
 package:flutter/…/rendering/object.dart
#3      RenderSliverEdgeInsetsPadding.performLayout
 package:flutter/…/rendering/sliver_padding.dart
#4      RenderSliverPadding.performLayout
 package:flutter/…/rendering/sliver_padding.dart
...
The following RenderObject was being processed when the exception was fired: RenderSliverWaterfallFlow#aa835 relayoutBoundary=up3 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
RenderObject: RenderSliverWaterfallFlow#aa835 relayoutBoundary=up3 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
    needs compositing
    parentData: paintOffset=Offset(4.0, 0.0) (can use size)
    constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle, scrollOffset: 6661.4, remainingPaintExtent: 334.0, crossAxisExtent: 742.0, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 334.0, remainingCacheExtent: 834.0, cacheOrigin: -246.0)
    geometry: SliverGeometry(scrollExtent: 7229.4, paintExtent: 568.0, maxPaintExtent: 7229.4, hasVisualOverflow: true, cacheExtent: 814.0)
        scrollExtent: 7229.4
        paintExtent: 568.0
        maxPaintExtent: 7229.4
        hasVisualOverflow: true
        cacheExtent: 814.0
    currently live children: 0 to 17
    child with index 0: RenderIndexedSemantics#f7bcb relayoutBoundary=up4 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: crossAxisIndex=0;crossAxisOffset=0.0;trailingLayoutOffset=407.9;indexes[0, 2, 4, 6, 8, 10, 12, 14]; index=0; layoutOffset=0.0 (can use size)
        constraints: BoxConstraints(w=368.5, 0.0<=h<=Infinity)
        semantic boundary
        size: Size(368.5, 407.9)
        index: 0
        child: RenderRepaintBoundary#69a4b relayoutBoundary=up5 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
            needs compositing
            parentData: <none> (can use size)
            constraints: BoxConstraints(w=368.5, 0.0<=h<=Infinity)
            size: Size(368.5, 407.9)
            usefulness ratio: no metrics collected yet (never painted)
            child: RenderPadding#8344e relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
                parentData: <none> (can use size)
                constraints: BoxConstraints(w=368.5, 0.0<=h<=Infinity)
                size: Size(368.5, 407.9)
                padding: EdgeInsets.zero
                textDirection: ltr
                child: RenderSemanticsGestureHandler#2854f relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
                    parentData: offset=Offset(0.0, 0.0) (can use size)
                    constraints: BoxConstraints(w=368.5, 0.0<=h<=Infinity)
                    size: Size(368.5, 407.9)
                    gestures: tap
...
════════════════════════════════════════════════════════════════════════════════

Bad state: No element

线上出现几百个异常日志,本地测试无法复现。

872行代码片段截图
image

堆栈信息:
#0 ListMixin.reduce (dart:collection/list.dart:222)
#1 _CrossAxisChildrenData.insert (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:872)
#2 RenderSliverWaterfallFlow.performLayout (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:537)
#3 RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
#4 RenderSliverEdgeInsetsPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:137)
#5 RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:371)
#6 RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
#7 RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:510)
#8 RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1580)
#9 RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1489)
#10 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1757)
#11 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:887)
#12 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:504)
#13 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:892)
#14 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370)
#15 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146)
#16 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083)
#17 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997)
#18 _rootRun (dart:async/zone.dart:1426)
#19 _CustomZone.run (dart:async/zone.dart:1328)
#20 _CustomZone.runGuarded (dart:async/zone.dart:1236)
#21 _invoke (dart:ui/hooks.dart:151)
#22 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308)
#23 _drawFrame (dart:ui/hooks.dart:115)

双瀑布流时的性能问题

  1. 当使用2个瀑布流用CustomScrollView链接时, 滑动到第二个瀑布流在视窗内, 第一个瀑布流已经不在视口内, 但是每滑动一下,第一个瀑布流的所有item都会全部重新build,导致严重性能问题。
    eg:
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:waterfall_flow/waterfall_flow.dart';

List<Color> colors = <Color>[];

class WaterFallDemo extends StatefulWidget {
  @override
  WaterFallDemoState createState() => WaterFallDemoState();
}

class WaterFallDemoState extends State<WaterFallDemo> {
  int crossAxisCount = 4;
  double crossAxisSpacing = 5.0;
  double mainAxisSpacing = 5.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverToBoxAdapter(
            child: Container(
              height: 200,
              color: Colors.red,
              alignment: Alignment.center,
              child: const Text(
                'I\'m the first water slivers',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 20,
                ),
              ),
            ),
          ),
          SliverWaterfallFlow(
            gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
              crossAxisCount: crossAxisCount,
              crossAxisSpacing: crossAxisSpacing,
              mainAxisSpacing: mainAxisSpacing,
              collectGarbage: (List<int> garbages) {
                print('collect first waterfall garbage : $garbages');
              },
              viewportBuilder: (int firstIndex, int lastIndex) {
                print('first waterfall  viewport : [$firstIndex,$lastIndex]');
              },
            ),
            delegate: SliverChildBuilderDelegate((BuildContext c, int index) {
              return Item(index, 'first waterfall');
            }, childCount: 50),
          ),
          SliverToBoxAdapter(
            child: Container(
              margin: EdgeInsets.only(top: 40),
              height: 200,
              color: Colors.red,
              alignment: Alignment.center,
              child: const Text(
                'I\'m the second water slivers',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 20,
                ),
              ),
            ),
          ),
          SliverWaterfallFlow(
            gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
              crossAxisCount: crossAxisCount,
              crossAxisSpacing: crossAxisSpacing,
              mainAxisSpacing: mainAxisSpacing,
              collectGarbage: (List<int> garbages) {
                print('collect second waterfall garbage : $garbages');
              },
              viewportBuilder: (int firstIndex, int lastIndex) {
                print('second waterfall viewport : [$firstIndex,$lastIndex]');
              },
            ),
            delegate: SliverChildBuilderDelegate((BuildContext c, int index) {
              return Item(index, 'second waterfall');;
            }, childCount: 50),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            crossAxisCount++;
            //mainAxisSpacing+=5.0;
            //crossAxisSpacing+=5.0;
          });
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

class Item extends StatelessWidget {
  int index;
  String waterfallName;
  Item(this.index, this.waterfallName);

  @override
  Widget build(BuildContext context) {
    print('build $waterfallName $index');
    final Color color = getRandomColor(index);
    return Container(
      child: Container(
        decoration: BoxDecoration(
            border: Border.all(color: Colors.black),
            color: getRandomColor(index)),
        alignment: Alignment.center,
        child: Text(
          '$index',
          style: TextStyle(
              color:
                  color.computeLuminance() < 0.5 ? Colors.white : Colors.black),
        ),
        //height: index == 5 ? 1500.0 : 100.0,
        height: ((index % 3) + 1) * 100.0,
      ),
    );
  }
}

Color getRandomColor(int index) {
  if (index >= colors.length) {
    colors.add(Color.fromARGB(255, Random.secure().nextInt(255),
        Random.secure().nextInt(255), Random.secure().nextInt(255)));
  }

  return colors[index];
}

输出日志:
image

flutter version >=1.17.0

Why flutter version must be >= 1.17.0
environment:
sdk: ">=2.6.0 <3.0.0"
flutter: ">=1.17.0"

log:
depends on flutter_staggered_grid_view >=0.3.2 which requires Flutter SDK version >=1.17.0, version solving failed.
pub upgrade failed (1; Because flutter_demo depends on flutter_staggered_grid_view >=0.3.2 which requires Flutter SDK version >=1.17.0, version solving failed.)

Extend LastChildLayoutType.fullCrossAxisExtent to leading item

Hi,
is there a way to extend fullCrossAxisExtent to the first item?
Imagine a loader on the top of the grid or a button to reload content in case of errors ...

      lastChildLayoutTypeBuilder: (index) {
        if ((index == 0 && reloadRequired) ||
            ((index == 0 && isLoadingAll) ||
                (index == dataLength - 1 && isLoadingMore)) ||
            (index == dataLength - 1 && !isLoadingAll)) {
          return LastChildLayoutType.fullCrossAxisExtent;
        }

        return LastChildLayoutType.none;
      },

Thanks,
Andrea

Exception has occurred. StateError (Bad state: No element)

I have All exceptions turned on and it always crashes.

double get maxLeadingLayoutOffset {
try {
return leadingItems
.reduce( // <=================== here
(WaterfallFlowParentData curr, WaterfallFlowParentData next) =>
curr.layoutOffset >= next.layoutOffset ? curr : next)
.layoutOffset;
} catch (e) {
return 0.0;
}
}

iOS 长时间挂起后台后,出现skeleton 铺满全屏。。。。[Bug report]

Version

3.0.2

Platforms

iOS

Device Model

iPhone 12(iOS 16)

flutter info

[✓] Flutter (Channel stable, 3.7.0, on macOS 11.6.4 20G417 darwin-x64, locale zh-Hans-US)
    • Flutter version 3.7.0 on channel stable at /Users/apple/Documents/work/flutter/flutter/3.7
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b06b8b2710 (6 weeks ago), 2023-01-23 16:55:55 -0800
    • Engine revision b24591ed32
    • Dart version 2.19.0
    • DevTools version 2.20.1
    • Pub download mirror https://pub.flutter-io.cn
    • Flutter download mirror https://storage.flutter-io.cn

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/apple/Library/Android/sdk
    • Platform android-33, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 13C100
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 11.6.4 20G417 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 110.0.5481.177

[✓] HTTP Host Availability
    • All required HTTP hosts are available

How to reproduce?

真机使用,后台运行,过一段时间后,会出现skeleton 铺满全屏。
image

不知道啥原因。。。

Logs

由于是真机,没有办法看到日志

Example code (optional)

No response

Contact

[email protected]

刷新数据后,瀑布流的item会出现错位

通过筛选项对瀑布流的数据进行刷新,当获取到的数据为空时,不显示信息。(正确)
取消筛选项,重新加载瀑布流的数据,此时出现item错位,瀑布流的前两个位置或者一个位置会空出。

CustomScrollView里的SliverWaterfallFlow可以指定childCount数量吗

你好,我想请问一下,这个方式生成可以指定生成数量吗?
child: CustomScrollView( slivers: [ SliverWaterfallFlow( delegate: SliverChildBuilderDelegate((BuildContext c, int index) { return Container( decoration: BoxDecoration(color: Colors.grey[300]), alignment: Alignment.center, child: Text( '$index', style: TextStyle(color: Colors.black), ), //height: index == 5 ? 1500.0 : 100.0, height: ((index % 3) + 1) * 100.0, ); }), gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 5, mainAxisSpacing: 5, collectGarbage: (List<int> garbages) { print('collect garbage : $garbages'); }, viewportBuilder: (int firstIndex, int lastIndex) { print('viewport : [$firstIndex,$lastIndex]'); }, ), ) ], ),

No such method error

I am getting a noSuchMethod error when running on a Simulator (iOS).

The issue seems similar to what has been raised here :

#16

because I dont always get this error. It happens on scrolling (when there is more than 1 page of images).

image

When I look at the line 479 in sliver_waterfall_flow it shows :

if (data.layoutOffset < -precisionErrorTolerance) {

If I scroll very fast up and down I get the error and my list of (say) 20 items either gets cleared or goes down to 1 or two items (Only 1 or 2 items are shown).

My images were small (20k) apart from a few that were very large (5mb). When I remove the large images from the list - I dont get the issue at all.

Additionally - I am also experiencing jumping of images within the Masonary view.

3.16.0 不满一屏时,item不能响应点击事件

Version

3.0.2

Platforms

dart, Android, iOS, macOS, Web, Windows, Linux

Device Model

all

flutter info

flutter doctor -v
[✓] Flutter (Channel stable, 3.16.0, on macOS 14.1.1 23B81 darwin-arm64, locale
    zh-Hans-CN)
    • Flutter version 3.16.0 on channel stable at /Users/ldd/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision db7ef5bf9f (5 days ago), 2023-11-15 11:25:44 -0800
    • Engine revision 74d16627b9
    • Dart version 3.2.0
    • DevTools version 2.28.2

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/ldd/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = /Users/ldd/Library/Android/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      17.0.6+0-17.0.6b829.9-10027231)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15A507
    • CocoaPods version 1.14.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • android-studio-dir = /Applications/Android Studio.app
    • Java version OpenJDK Runtime Environment (build
      17.0.6+0-17.0.6b829.9-10027231)

[✓] Android Studio (version 2023.1)
    • Android Studio at /Users/ldd/Applications/Android Studio Hedgehog 2023.1.1
      RC 3.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      17.0.7+0-17.0.7b1000.6-10550314)

[!] Android Studio (version unknown)
    • Android Studio at /Users/ldd/Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    ✗ Unable to determine Android Studio version.
    • Java version OpenJDK Runtime Environment (build
      17.0.9+0-17.0.9b1000.46-11084592)

[✓] IntelliJ IDEA Ultimate Edition (version EAP IU-233.11555.11)
    • IntelliJ at /Applications/IntelliJ IDEA.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] VS Code (version 1.84.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.48.0

[✓] Proxy Configuration
    • HTTP_PROXY is set
    • NO_PROXY is 127.0.0.1,localhost,43.139.7.211,0.0.0.0,::1
    • NO_PROXY contains localhost
    • NO_PROXY contains 127.0.0.1
    • NO_PROXY contains ::1

[✓] Connected device (3 available)
    • 梁典典的iPhone (mobile) • 00008101-00064D900E22001E • ios            • iOS
      17.1.1 21B91
    • macOS (desktop)     • macos                     • darwin-arm64   • macOS
      14.1.1 23B81 darwin-arm64
    • Chrome (web)        • chrome                    • web-javascript • Google
      Chrome 119.0.6045.159

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.

How to reproduce?

见代码

点击红色区域,会发现不能执行 onTap里面的函数
image

Logs

Example code (optional)

import 'package:flutter/material.dart';
import 'package:waterfall_flow/waterfall_flow.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  final datas = List.generate(2, (index) => '$index');
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('bug'),
        ),
        body: CustomScrollView(
          reverse: true,
          slivers: [
            SliverWaterfallFlow(
                delegate: SliverChildBuilderDelegate((context, index) {
                  final item = datas[index];
                  return GestureDetector(
                    onTap: (){
                      print('>>>>>$index'); //----》不能响应点击事件
                    },
                    child: Container(
                      width: 66,
                      height: 66,
                      margin: EdgeInsets.only(bottom: 12),
                      color: Colors.red,
                      child: Text('$index'),
                    ),
                  );
                },
                    childCount: datas.length),
                gridDelegate: const SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 1, closeToTrailing: true))
          ],
        ),
      ),
    );
  }
}

Contact

No response

using WaterfallFlow with expanded and False shrinkWrap

in this code i get visible error and how can i have WaterfallFlow into ListView?

The getter 'visible' was called on null.
Receiver: null
Tried calling: visible

class SampleCode extends StatelessWidget {
  List<Color> colors = <Color>[];

  @override
  Widget build(BuildContext context) {
    final double screenWidthSize = MediaQuery.of(context).size.width;

    return Scaffold(
      appBar: AppBar(
        title: const Text('RandomSized'),
      ),
      body: ListView(
        children: <Widget>[
          Container(
            height: 100.0,
            child: Text('TEST'),
          ),
          LayoutBuilder(
              builder: (BuildContext context, BoxConstraints constraints){
                int _crossAxisCount = 0;
                if (screenWidthSize > 720) {
                  _crossAxisCount = 3;
                } else if (screenWidthSize > 520) {
                  _crossAxisCount = 2;
                } else {
                  _crossAxisCount = 1;
                }
                return Expanded(
                  child: WaterfallFlow.builder(
                    padding: const EdgeInsets.all(5.0),
                    shrinkWrap: false,
                    gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
                      crossAxisCount: _crossAxisCount,
                      crossAxisSpacing: 4,
                      mainAxisSpacing: 4,
                    ),
                    itemBuilder: (BuildContext c, int index) {
                      final Color color = getRandomColor(index);
                      return Container(
                        decoration: BoxDecoration(
                            border: Border.all(color: Colors.black),
                            color: getRandomColor(index)),
                        alignment: Alignment.center,
                        child: Text(
                          '$index ' + 'TestString' * 10 * (index % 3 + 1),
                          style: TextStyle(
                              color: color.computeLuminance() < 0.5
                                  ? Colors.white
                                  : Colors.black),
                        ),
                        //height: ((index % 3) + 1) * 100.0,
                      );
                    },
                    itemCount: 22,
                  ),
                );
              }
          )
        ],
      ),
    );
  }

  Color getRandomColor(int index) {
    if (index >= colors.length) {
      colors.add(Color.fromARGB(255, Random.secure().nextInt(255),
          Random.secure().nextInt(255), Random.secure().nextInt(255)));
    }

    return colors[index];
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.