Flutter 实现仿微信群头像排列相关代码-(头像为圆形)


文章目录

  • 前言
  • 一、需要实现的效果如下
  • 二、flutter实现代码如下:
  • 总结


前言

最近写flutter项目,其中就有群聊的相关功能,我们需要实现群头像的拼接,这时候就需要把几个用户的头像按照一定的规则排列起来;


一、需要实现的效果如下

1、UI设计图:
Flutter 实现仿微信群头像排列相关代码-(头像为圆形)_第1张图片

二、flutter实现代码如下:

1、重点是RoomAvatarPainter画头像的代码
2、如果还不明白的朋友可以私信问我

class AvatarImageUtil {
  static Future<String?> generateAvatarPath(List<String?> avatars) async {
    final String key = Md5Util.stringToMd5(avatars.length > 9 ? avatars.sublist(0, 9).join('-') : avatars.join('-'));
    var newFile = await FileDirUtils.generateManageDirFile(FileDirUtils.avatarDir, "png", fileName: key);
    if (newFile.existsSync()) {
      return newFile.path;
    }
    var path = newFile.path;
    final List<ui.Image> images = [];
    for (final element in avatars) {
      final image = await _download(element);
      images.add(image);
    }
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(recorder);
    const imageSize = 320.0;
    RoomAvatarPainter().paint(canvas, const Size(imageSize, imageSize), images);
    final picture = recorder.endRecording();
    final img = await picture.toImage(imageSize.ceil(), imageSize.ceil());
    final byteData = await img.toByteData(format: ui.ImageByteFormat.png);
    final pngBytes = byteData!.buffer.asUint8List();
    final file = await File(path).create();
    file.writeAsBytesSync(pngBytes);
    return path;
  }

  static Future<ui.Image> _download(String? url) async {
    if (url == null || url.isEmpty) {
      return load(AppConstant.defaultAvatarImage);
    }
    try {
      final file = await DefaultCacheManager().getSingleFile(url);
      final ui.Codec codec = await ui.instantiateImageCodec(file.readAsBytesSync());
      final ui.FrameInfo fi = await codec.getNextFrame();
      return fi.image;
    } catch (e) {
      return load(AppConstant.defaultAvatarImage);
    }
  }

  /// 通过assets路径,获取资源图片
  static Future<ui.Image> load(String asset) async {
    final ByteData data = await rootBundle.load(asset);
    final ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
    final ui.FrameInfo fi = await codec.getNextFrame();
    return fi.image;
  }

  AvatarImageUtil._();
}

class RoomAvatarPainter {
  final Paint _paint = Paint()
    ..color = const Color(0xFFE6E6E6) // 画笔颜色
    ..strokeCap = StrokeCap.round //画笔笔触类型
    ..isAntiAlias = true //是否启动抗锯齿
    ..strokeWidth = 6.0 //画笔的宽度
    ..style = PaintingStyle.fill; // 样式

  paint(Canvas canvas, Size size, List<ui.Image> images) {
    Paint backgroundPaint = Paint()..color = const Color(0xFFFFFFFF);
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), backgroundPaint);

    final int count = images.length;

    //头像的布局规则
    List<List<int>> layoutRules = [
      [1], // 1
      [2], // 2
      [1, 2], // 3
      [2, 2], // 4
      [2, 3], // 5
      [3, 3], // 6
      [1, 3, 3], // 7
      [2, 3, 3], // 8
      [3, 3, 3], // 9
    ];

    final rule = layoutRules[count - 1];

    final double imageSize = size.width / 3;
    final double totalHeight = imageSize * rule.length;
    final double startY = (size.height - totalHeight) / 2;

    int imageIndex = 0;

    for (int i = 0; i < rule.length; i++) {
      final rowCount = rule[i];
      final rowY = startY + i * imageSize;
      final rowX = (size.width - rowCount * imageSize) / 2;

      for (int j = 0; j < rowCount; j++) {
        final image = images[imageIndex++];
        final srcRect = Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble());
        final dstRect = Rect.fromLTWH(rowX + j * imageSize, rowY, imageSize, imageSize);

        canvas.save();
        canvas.clipPath(Path()..addOval(dstRect));
        canvas.drawImageRect(image, srcRect, dstRect, _paint);
        canvas.restore();
      }
    }
  }
}

总结

这就是Flutter 实现仿微信群头像排列相关代码,希望能帮助到你!

你可能感兴趣的:(flutter,flutter)