flutter|Flutter最酷炫瀑布流实现

  • 背景
公司APP首页列表有此需求
  • 使用哪些组件
StaggeredGridView.countBuilder
  • 如何实现,难点在哪里
瀑布流的宽度与高度。
宽度=(屏幕宽—组件间隙) / 2
高度=图片高度进行设置
这样才能实现并展示瀑布流的效果
在pubspec.yaml 文件 添加 flutter_staggered_grid_view: ^0.4.1
flutter_screenutil: ^5.0.0这个是屏幕适配使用
使用过程中有什么问题可以自己私信我
  • 最终效果图
    给你们配置了网红孙一宁flutter|Flutter最酷炫瀑布流实现
    文章图片
FeedListView.dart文件
class FeedListView extends StatefulWidget { final FeedMode? mode; FeedListView({Key? key, this.mode}) : super(key: key); @override FeedListViewState createState() => FeedListViewState(); }class FeedListViewState extends State { List imgList = [ 'https://bkimg.cdn.bcebos.com/pic/500fd9f9d72a6059252d1977427a239b033b5bb50c05?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UxNTA=,g_7,xp_5,yp_5/format,f_auto', 'https://gimg2.baidu.com/image_search/src=https://www.it610.com/article/http%3A%2F%2Fnimg.ws.126.net%2F%3Furl%3Dhttp%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0624%2Fca3f3547j00qv6yuq002ic000mn0148c.jpg%26thumbnail%3D650x2147483647%26quality%3D80%26type%3Djpg&refer=http%3A%2F%2Fnimg.ws.126.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1636620826&t=1f7e60c5d4a5baadafbae5d25dfdae39', 'https://bkimg.cdn.bcebos.com/pic/0d338744ebf81a4c510f10a4bd647759252dd42a0805?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UyMjA=,g_7,xp_5,yp_5/format,f_auto', 'https://upload-images.jianshu.io/upload_images/6865547-100e574111cf0696.png?imageMogr2/auto-orient/strip|imageView2/2/w/507/format/webp', 'https://bkimg.cdn.bcebos.com/pic/500fd9f9d72a6059252d1977427a239b033b5bb50c05?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UxNTA=,g_7,xp_5,yp_5/format,f_auto', 'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/76a788337365419c971a94a5fbdbc4f8~tplv-k3u1fbpfcp-zoom-crop-mark:1304:1304:1304:734.awebp?', 'https://upload-images.jianshu.io/upload_images/6865547-100e574111cf0696.png?imageMogr2/auto-orient/strip|imageView2/2/w/507/format/webp', 'https://bkimg.cdn.bcebos.com/pic/0ff41bd5ad6eddc451dad5965395a1fd5266d0169502?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UxMTY=,g_7,xp_5,yp_5/format,f_auto', 'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/76a788337365419c971a94a5fbdbc4f8~tplv-k3u1fbpfcp-zoom-crop-mark:1304:1304:1304:734.awebp?', 'https://upload-images.jianshu.io/upload_images/6865547-100e574111cf0696.png?imageMogr2/auto-orient/strip|imageView2/2/w/507/format/webp', 'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/76a788337365419c971a94a5fbdbc4f8~tplv-k3u1fbpfcp-zoom-crop-mark:1304:1304:1304:734.awebp?', 'https://upload-images.jianshu.io/upload_images/6865547-100e574111cf0696.png?imageMogr2/auto-orient/strip|imageView2/2/w/507/format/webp', ]; List modelList = []; @override void initState() { super.initState(); var ii = new Random().nextInt(5); var i = 0; imgList.forEach((element) { var _random = new Random(); int next(int min, int max) => min + _random.nextInt(max - min); var c = next(200, 800); i++; var model = WaterfallsFlowModel( imageUrl: element, content: i > ii ? '影片名称影片名称影片名称影片名称影片名称' : '影片名称', like: '2313', imageHeight: c); modelList.add(model); }); }@override Widget build(BuildContext context) { homeProvider = context.watch(); return Container( child: StaggeredGridView.countBuilder( padding: EdgeInsets.symmetric(horizontal: 5.w), // shrinkWrap: true, crossAxisCount: 4, itemCount: provider.modelList.length, itemBuilder: (context, i) { if (i == 0 && mode == FeedMode.user) { return UserInfoTop(); } return GestureDetector( onTap: _onTap, child: FeedWidget( mode: mode, model: provider.modelList[i], ), ); }, staggeredTileBuilder: (index) { return StaggeredTile.fit(2); }), ); }

WaterfallsFlowModel.dart
class WaterfallsFlowModel { String? imageUrl; String? content; String? name; String? avatarUrl; String? like; bool? isLise; int? imageWidth; int? imageHeight; WaterfallsFlowModel( {this.imageUrl, this.content, this.name, this.avatarUrl, this.like, this.isLise, this.imageWidth, this.imageHeight}); }

【flutter|Flutter最酷炫瀑布流实现】FeedWidget.dart 瀑布流Widget
///瀑布流组件 class FeedWidget extends StatefulWidget { final String? imageUrl; final WaterfallsFlowModel? model; final FeedMode? mode; FeedWidget({Key? key, this.imageUrl, this.model, this.mode}) : super(key: key); @override _FeedWidgetState createState() => _FeedWidgetState(); }class _FeedWidgetState extends State { var imageWidth = ScreenUtil().screenWidth - 30.w; var isMaxTwo = false; late WaterfallsFlowModel model; var isLike = false; @override Widget build(BuildContext context) { model = widget.model!; _didExceedOneMoreLines(model.content!, ScreenUtil().screenWidth / 2 - 120.w, TextStyle(fontSize: 30.sp)); return Container( margin: EdgeInsets.fromLTRB(5.w, 5.w, 5.w, 5.w), height: isMaxTwo ? model.imageHeight!.w + 190.w : model.imageHeight!.w + 150.w, decoration: BoxDecoration( borderRadius: BorderRadius.all( Radius.circular(8.w), ), color: Colors.white, boxShadow: [ BoxShadow( // 设置第一个阴影效果 color: Color(0xfff2f2f4), // 阴影颜色为绿色 blurRadius: 8.w, // 模糊半径为10 ), // 延伸半径为10 ]), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _imageWidget(), _movieWidget(), _likeWidget(), ], ), ); }///1.顶部图片 _imageWidget() { return Image.network(model.imageUrl!, width: imageWidth, height: model.imageHeight!.w, ); }///2.影片名称 _movieWidget() { return Padding( padding: EdgeInsets.fromLTRB(20.w, 20.w, 20.w, 0), child: Text( model.content!, overflow: TextOverflow.ellipsis, style: TextStyle( color: KColor.black, fontWeight: FontWeight.w700, fontSize: 30.sp, ), maxLines: 2, ), ); }///3.用户名称与点赞数量 _likeWidget() { return Padding( padding: EdgeInsets.all(20.w), child: Row( children: [ widget.mode == FeedMode.user ? _viewsWidget() : _userInfoWidget(), SizedBox(width: 4.w), Text('111', overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle(color: Color(0xFF66667E), fontSize: 24.sp)) ], ), ); }///3.1 用户信息 _userInfoWidget() { return Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: () { }, child: Image.network(model.imageUrl!, width: imageWidth, height: model.imageHeight!.w, ), SizedBox(width: 12.w), Expanded( child: GestureDetector( onTap: () { }, child: Text( '用户名称用户名称用户名称', overflow: TextOverflow.ellipsis, style: TextStyle( color: Color(0xFF66667E), fontSize: 24.sp, ), maxLines: 1, ), ), ), SizedBox(width: 20.w), ], ), ); }///3.2 浏览量 _viewsWidget() { return Expanded( child: Row( children: [ Text('111', overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle(color: Color(0xFF66667E), fontSize: 24.sp)) ], ), ); }_didExceedOneMoreLines(String text, double width, TextStyle style) { final span = TextSpan(text: text, style: style); final tp = TextPainter(text: span, maxLines: 1, textDirection: TextDirection.ltr); tp.layout(maxWidth: width); if (tp.didExceedMaxLines) { isMaxTwo = true; } else { isMaxTwo = false; } } }

    推荐阅读