You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:在Row中保持AspectRatio与图片原比例并适配全屏宽度

解决方案

要实现这个布局,核心是先确定未知比例图片的宽高比,再结合屏幕宽度计算出Row的合适高度,确保两个元素都保持原比例且填满屏幕宽度。具体步骤如下:

1. 获取图片的宽高比

因为图片比例未知,需要先加载图片获取其原始尺寸,计算出宽高比(宽度/高度)。可以通过ImageStreamListener监听图片加载完成事件来获取尺寸。

2. 计算Row的高度

假设屏幕宽度为screenWidth,图片宽高比为imageRatio,第一个元素是1:1的AspectRatio,那么Row的高度rowHeight可以通过以下公式推导:

  • 第一个元素的宽度 = rowHeight(因为1:1,宽高相等)
  • 第二个元素的宽度 = screenWidth - rowHeight
  • 要保持图片原比例,需满足 (screenWidth - rowHeight) / rowHeight = imageRatio
  • 解方程得:rowHeight = screenWidth / (1 + imageRatio)

3. 构建布局

用LayoutBuilder获取屏幕可用宽度,结合计算出的高度构建Row,确保两个元素的尺寸匹配且保持原比例。

完整代码示例:

import 'package:flutter/material.dart';

class RatioRowLayout extends StatefulWidget {
  const RatioRowLayout({super.key});

  @override
  State<RatioRowLayout> createState() => _RatioRowLayoutState();
}

class _RatioRowLayoutState extends State<RatioRowLayout> {
  Size? _imageSize;

  @override
  void initState() {
    super.initState();
    _loadImageDimensions();
  }

  // 加载图片并获取尺寸
  void _loadImageDimensions() {
    final imageProvider = AssetImage('assets/your_image.png');
    final imageStream = imageProvider.resolve(const ImageConfiguration());
    
    imageStream.addListener(ImageStreamListener((imageInfo, _) {
      if (mounted) {
        setState(() {
          _imageSize = Size(
            imageInfo.image.width.toDouble(),
            imageInfo.image.height.toDouble(),
          );
        });
      }
    }));
  }

  @override
  Widget build(BuildContext context) {
    // 图片未加载完成时显示加载指示器
    if (_imageSize == null) {
      return const Center(child: CircularProgressIndicator());
    }

    final imageRatio = _imageSize!.width / _imageSize!.height;

    return LayoutBuilder(
      builder: (context, constraints) {
        final screenWidth = constraints.maxWidth;
        final rowHeight = screenWidth / (1 + imageRatio);

        return SizedBox(
          width: screenWidth,
          height: rowHeight,
          child: Row(
            children: [
              // 1:1比例的子元素
              AspectRatio(
                aspectRatio: 1,
                child: Container(
                  color: Colors.blueAccent,
                  // 替换成你的实际内容
                  child: const Center(child: Text('1:1 Element')),
                ),
              ),
              // 未知比例的图片
              SizedBox(
                width: screenWidth - rowHeight,
                height: rowHeight,
                child: Image.asset(
                  'assets/your_image.png',
                  fit: BoxFit.contain,
                  width: double.infinity,
                  height: double.infinity,
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}

关键说明

  • 使用BoxFit.contain确保图片完整显示且保持原比例,如果需要填充容器可以改用BoxFit.cover(会裁剪部分内容)。
  • 图片尺寸只会加载一次,避免重复计算。
  • LayoutBuilder能实时获取父容器的可用宽度,适配不同屏幕尺寸。

内容的提问来源于stack exchange,提问作者Sagi Buchbinder Shadur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 23:00:41