Flutter仿照微信实现九宫格头像

一、效果图

2、主要代码

c 复制代码
import 'dart:io';
import 'dart:math';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

class ImageGrid extends StatelessWidget {
  final List<String> imageUrls; // 假设这是你的图片URL列表
  final double containerSize = 72.0; // 容器大小
  final double padding = 3.0; // 图片距离容器的宽度
  final double spacing = 2.0; // 图片之间的间隔

  ImageGrid({required this.imageUrls});

  double calculateImageWidth(int count) {
    double containerWidth = 72;
    double padding = 3;
    double gap = 2;

    if (count <= 4) {
      return (containerWidth - padding * 2 - gap) / 2;
    } else {
      return (containerWidth - padding * 2 - gap * 2) / 3;
    }
  }

  Widget _buildGrid() {
    double imageWidth = calculateImageWidth(imageUrls.length);
    int imageCount = imageUrls.length > 9 ? 9 : imageUrls.length;
    if (imageCount == 1) {
      // 一张图片铺满
      return Center(
        child: Container(
          width: containerSize,
          height: containerSize,
          child: Image.network(
            imageUrls[0],
            fit: BoxFit.cover,
          ),
        ),
      );
    } else {
      int rowCount = 1; //几行
      int firstNumber = 0; //第一行显示几个0不做特别处理
      int cellCount = 1; //几列
      if (imageCount == 2) {
        rowCount = 1;
        cellCount = 2;
      } else if (imageCount == 4 || imageCount == 6) {
        rowCount = 2;
        cellCount = imageCount == 4 ? 2 : 3;
      } else if (imageCount == 9) {
        rowCount = 3;
        cellCount = 3;
      } else if (imageCount == 3) {
        rowCount = 2;
        firstNumber = 1;
        cellCount = 2;
      } else if (imageCount == 5) {
        rowCount = 2;
        firstNumber = 2;
        cellCount = 3;
      } else if (imageCount == 7) {
        rowCount = 3;
        firstNumber = 1;
        cellCount = 3;
      } else if (imageCount == 8) {
        rowCount = 3;
        firstNumber = 2;
        cellCount = 3;
      }
      // 两张图片并排
      return Padding(
        padding: EdgeInsets.all(spacing),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            if (firstNumber != 0)
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: List.generate(firstNumber, (cellIndex) {
                  return Row(
                    children: [
                      getImageWidget(cellIndex, imageWidth),
                      if (cellIndex != firstNumber - 1)
                        SizedBox(width: spacing),
                    ],
                  );
                }),
              ),
            if (firstNumber != 0 && rowCount > 1) SizedBox(height: spacing),
            ...List.generate(rowCount - (firstNumber != 0 ? 1 : 0), (rowIndex) {
              return Column(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: List.generate(cellCount, (cellIndex) {
                      int index =
                          firstNumber + rowIndex * cellCount + cellIndex;
                      return Row(
                        children: [
                          getImageWidget(index, imageWidth),
                          if (cellIndex != cellCount - 1)
                            SizedBox(width: spacing),
                        ],
                      );
                    }),
                  ),
                  if (rowIndex != rowCount - (firstNumber != 0 ? 2 : 1))
                    SizedBox(height: spacing),
                ],
              );
            }),
          ],
        ),
      );
    }
  }

//生成 图片wrapper
  getImageWidget(int index, double width) {
    if (!imageUrls[index].contains("http")) {
      return Image.file(File(imageUrls[index]),
          width: width, height: width, fit: BoxFit.cover);
    } else {
      return CachedNetworkImage(
        imageUrl: imageUrls[index],
        width: width,
        height: width,
        fit: BoxFit.cover,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(6),
      child: Container(
        width: containerSize,
        height: containerSize,
        decoration: BoxDecoration(
          //  color: Color(0xFFEEEEEE),
          color: Color.fromARGB(255, 243, 4, 4),
          borderRadius: BorderRadius.circular(6),
        ),
        child: _buildGrid(),
      ),
    );
  }
}
相关推荐
problc26 分钟前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
陈思杰系统思考Jason3 小时前
系统思考—深层结构
百度·微信·微信公众平台·新浪微博·微信开放平台
lqj_本人9 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人12 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
起司锅仔16 小时前
Flutter启动流程(2)
flutter
hello world smile19 小时前
最全的Flutter中pubspec.yaml及其yaml 语法的使用说明
android·前端·javascript·flutter·dart·yaml·pubspec.yaml
lqj_本人19 小时前
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
flutter·harmonyos
iFlyCai19 小时前
极简实现酷炫动效:Flutter隐式动画指南第二篇之一些酷炫的隐式动画效果
flutter
lqj_本人20 小时前
Flutter&鸿蒙next 中使用 MobX 进行状态管理
flutter·华为·harmonyos
lqj_本人20 小时前
Flutter&鸿蒙next 中的 setState 使用场景与最佳实践
flutter·华为·harmonyos