Flutter实现图片堆叠组件并添加总用户数显示功能
需求:实现带总用户数的堆叠头像组件
我参考视频实现了图片堆叠效果,但还不满足需求——需要在这个堆叠结构基础上显示总用户数(类似带“+X”的圆形标识样式)。Pub上的相关包都不符合要求,求帮忙。
现有堆叠组件代码
import 'package:flutter/material.dart'; class StackedWidgets extends StatelessWidget { final List<Widget> items; final TextDirection direction; final double size; final double xShift; const StackedWidgets({ Key? key, required this.items, this.direction = TextDirection.ltr, this.size = 100, this.xShift = 20, }) : super(key: key); @override Widget build(BuildContext context) { final allItems = items .asMap() .map((index, item) { final left = size - xShift; final value = Container( width: size, height: size, child: item, margin: EdgeInsets.only(left: left * index), ); return MapEntry(index, value); }) .values .toList(); return Stack( children: direction == TextDirection.ltr ? allItems.reversed.toList() : allItems, ); } }
组件使用代码
Widget buildStackedImages({ TextDirection direction = TextDirection.ltr, }) { final double size = 100; final double xShift = 20; final urlImages = [ 'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=633&q=80', 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80', 'https://images.unsplash.com/photo-1616766098956-c81f12114571?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80', ]; final items = urlImages.map((urlImage) => buildImage(urlImage)).toList(); return StackedWidgets( direction: direction, items: items, size: size, xShift: xShift, ); } Widget buildImage(String urlImage) { final double borderSize = 5; return ClipOval( child: Container( padding: EdgeInsets.all(borderSize), color: Colors.white, child: ClipOval( child: Image.network( urlImage, fit: BoxFit.cover, ), ), ), ); }
解决方案
修改StackedWidgets组件,新增总用户数参数,当总数量超过显示的头像数时,自动添加显示剩余数量的圆形组件:
修改后的StackedWidgets组件
import 'package:flutter/material.dart'; class StackedWidgets extends StatelessWidget { final List<Widget> items; final int totalCount; // 总用户数 final TextDirection direction; final double size; final double xShift; final int displayCount; // 最多显示的头像数量 const StackedWidgets({ Key? key, required this.items, required this.totalCount, this.direction = TextDirection.ltr, this.size = 100, this.xShift = 20, this.displayCount = 3, }) : super(key: key); @override Widget build(BuildContext context) { List<Widget> displayItems = []; // 确定要显示的头像数量 int showItemCount = items.length > displayCount ? displayCount : items.length; displayItems.addAll(items.take(showItemCount)); // 总数量超过显示数时,添加剩余数量组件 if (totalCount > showItemCount) { displayItems.add(_buildRemainingCountWidget(totalCount - showItemCount)); } final allItems = displayItems .asMap() .map((index, item) { final left = size - xShift; final value = Container( width: size, height: size, child: item, margin: EdgeInsets.only(left: left * index), ); return MapEntry(index, value); }) .values .toList(); return Stack( children: direction == TextDirection.ltr ? allItems.reversed.toList() : allItems, ); } // 构建剩余数量显示组件 Widget _buildRemainingCountWidget(int count) { return ClipOval( child: Container( width: size, height: size, color: Colors.grey[300], child: Center( child: Text( "+$count", style: TextStyle( fontSize: size * 0.4, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), ), ); } }
修改后的使用代码
Widget buildStackedImages({ TextDirection direction = TextDirection.ltr, }) { final double size = 100; final double xShift = 20; final urlImages = [ 'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=633&q=80', 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80', 'https://images.unsplash.com/photo-1616766098956-c81f12114571?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80', ]; final totalUsers = 10; // 设置总用户数 final items = urlImages.map((urlImage) => buildImage(urlImage)).toList(); return StackedWidgets( direction: direction, items: items, totalCount: totalUsers, size: size, xShift: xShift, displayCount: 3, // 控制显示3个头像,剩余数量显示+7 ); } Widget buildImage(String urlImage) { final double borderSize = 5; return ClipOval( child: Container( padding: EdgeInsets.all(borderSize), color: Colors.white, child: ClipOval( child: Image.network( urlImage, fit: BoxFit.cover, ), ), ), ); }
说明
- 通过
totalCount传入总用户数,displayCount控制最多显示的头像数量 - 当总用户数超过显示数时,自动追加带“+X”的圆形组件
- 可根据需求修改剩余数量组件的背景色、字体样式等
内容的提问来源于stack exchange,提问作者Abdullah T
相关产品推荐
相关产品推荐

