fluttercandies / waterfall_flow Goto Github PK
View Code? Open in Web Editor NEWA Flutter grid view which supports waterfall flow layout.
License: MIT License
A Flutter grid view which supports waterfall flow layout.
License: MIT License
3.0.3
Android
Pixel 3a API 34
[√] 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.
单个组件是一个套了好几层的 CachedNetworkImage,用一个 List.generate 生成 Waterflow 的 children 数组,下滑一段距离让上面的组件回收掉,然后再上滑让上面的组件重新加载,会出现重新布局、组件乱跳的情况
No response
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),
),
),
// ...
],
),
)
],
);
}
}
No response
footer可以用lastChildLayoutTypeBuilder
加,但是header怎么加?
请问这种带TabBarView的瀑布流如何做到整体滚动并刷新正常啊?
###6# 录屏
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;
}
}
大佬又遇到这个问题吗?
就是waterfall_flow和extended_nested_scroll_view一起使用再往上滚动的时候可能会出现无法滚上去(或者不流畅)的BUG
列表进入详情,从详情返回列表的时候会抖动
列表图片很小,列表页面保持了页面状态
waterfall_flow 3.0.2
日志:
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();
// });
// },
));
}
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 模式
代码
/// 默认的商品列表
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.
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),
);
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
2 #1 RenderSliverWaterfallFlow.performLayout (package:waterfall_flow/src/rendering/sliver_waterfall_flow.dart:199)
3 #2 RenderObject.layout (package:flutter/src/rendering/object.dart:1767)
4 #3 RenderSliverEdgeInsetsPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:134)
5 #4 RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:373)
6 #5 RenderObject.layout (package:flutter/src/rendering/object.dart:1767)
7 #6 RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:452)
8 #7 RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1444)
9 #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)
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 会报错
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;
}
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:
Expected:
Happening:
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
...
════════════════════════════════════════════════════════════════════════════════
线上出现几百个异常日志,本地测试无法复现。
堆栈信息:
#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)
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];
}
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.)
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
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;
}
}
It would be great if we could migrate this package to null-safety.
https://medium.com/dartlang/preparing-the-dart-and-flutter-ecosystem-for-null-safety-e550ce72c010
希望插入和删除重排时带动画效果。
3.0.2
iOS
iPhone 12(iOS 16)
[✓] 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
真机使用,后台运行,过一段时间后,会出现skeleton 铺满全屏。
不知道啥原因。。。
由于是真机,没有办法看到日志
No response
hi, is there an animated version of waterfall_flow? like AnimatedList?
通过筛选项对瀑布流的数据进行刷新,当获取到的数据为空时,不显示信息。(正确)
取消筛选项,重新加载瀑布流的数据,此时出现item错位,瀑布流的前两个位置或者一个位置会空出。
请问是否有办法在构建一个item的时候知道其所在的列数?
当瀑布流两列是,如何判断卡片是在左侧一列还是右侧一列
最一开始我想通过索引是奇数还是偶数判断,但是发现当某个卡片的长度没有超过上一个卡片的长度,新的卡片会和当前卡片在一列,导致奇偶判断失效了。
can we change crossAxisCount
count by using variable?
你好,我想请问一下,这个方式生成可以指定生成数量吗?
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]'); }, ), ) ], ),
I am getting a noSuchMethod error when running on a Simulator (iOS).
The issue seems similar to what has been raised here :
because I dont always get this error. It happens on scrolling (when there is more than 1 page of images).
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.0.2
dart, Android, iOS, macOS, Web, Windows, Linux
all
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.
见代码
无
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))
],
),
),
);
}
}
No response
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];
}
}
能不能有个firstChildLayoutTypeBuilder? 瀑布流的顶上如果要放一个 full width 的container 怎么做呢?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.