Created
April 29, 2022 09:58
-
-
Save mondoktamas/3f6f22a0d9dd6e96518afd67ca16d1d6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:math'; | |
import 'package:cached_network_image/cached_network_image.dart'; | |
import 'package:flutter/material.dart'; | |
class StackedAvatar extends StatelessWidget { | |
const StackedAvatar({ | |
required this.avatarUrls, | |
this.size = 32.0, | |
this.maxItemCount = 3, | |
this.overlap = 10.0, | |
this.borderWidth = 3.0, | |
}); | |
final List<String> avatarUrls; | |
final double size; | |
///the overlap in px of the avatars | |
final double overlap; | |
///maximum visible avatar items | |
final int maxItemCount; | |
///the outer border width around each avatar | |
final double borderWidth; | |
@override | |
Widget build(BuildContext context) { | |
final widgetWidth = (maxItemCount * size) - (overlap * (maxItemCount - 1)); | |
return Container( | |
height: size, | |
width: widgetWidth, | |
child: Stack( | |
children: List.generate( | |
min(maxItemCount, avatarUrls.length), | |
(index) => Positioned( | |
top: 0, | |
left: index * (size - overlap), | |
bottom: 0, | |
child: _StackedAvatar( | |
shouldClip: index != 0, | |
avatarUrl: avatarUrls[index], | |
overlap: overlap + borderWidth, | |
size: size, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
class _StackedAvatar extends StatelessWidget { | |
const _StackedAvatar({ | |
required this.avatarUrl, | |
this.overlap = 10, | |
this.size = 32, | |
this.shouldClip = false, | |
}); | |
final String avatarUrl; | |
final double size; | |
final double overlap; | |
final bool shouldClip; | |
@override | |
Widget build(BuildContext context) { | |
return SizedBox( | |
height: size, | |
width: size, | |
child: ClipPath( | |
clipper: _StackedAvatarClipper(shouldClip ? overlap : 0), | |
child: Image( | |
image: CachedNetworkImageProvider(avatarUrl), | |
), | |
), | |
); | |
} | |
} | |
class _StackedAvatarClipper extends CustomClipper<Path> { | |
final double shift; | |
_StackedAvatarClipper(this.shift); | |
@override | |
Path getClip(Size size) { | |
final path1 = Path()..addOval(Rect.fromLTRB(shift - size.width, 0, shift, size.height)); | |
final path2 = Path()..addOval(Rect.fromLTRB(0, 0, size.width, size.height)); | |
return Path.combine(PathOperation.reverseDifference, path1, path2); | |
} | |
@override | |
bool shouldReclip(covariant _StackedAvatarClipper oldClipper) => oldClipper.shift != shift; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment