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

Flutter中如何将相机组件适配到高度255、宽度全屏的容器中

解决方案

你可以通过对相机预览做比例计算+裁切适配的方式,在固定255高度、全屏宽度的容器内实现无拉伸的相机预览,修改后的完整代码如下:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';

List<CameraDescription> cameras;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();
  runApp(const MaterialApp(home: CameraApp()));
}

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

  @override
  _CameraAppState createState() => _CameraAppState();
}

class _CameraAppState extends State<CameraApp> {
  CameraController? controller;
  double? _cameraAspectRatio;

  @override
  void initState() {
    super.initState();
    controller = CameraController(cameras[0], ResolutionPreset.high);
    controller?.initialize().then((_) {
      if (!mounted) return;
      // 计算相机原生宽高比,竖屏场景下需要反转宽高
      _cameraAspectRatio = 1 / controller!.value.aspectRatio;
      setState(() {});
    });
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    const containerHeight = 255.0;
    final containerAspectRatio = screenWidth / containerHeight;

    if (controller == null || !controller!.value.isInitialized) {
      return const SizedBox.shrink();
    }

    return Scaffold(
      body: Column(
        children: [
          // 固定尺寸的相机容器
          SizedBox(
            width: screenWidth,
            height: containerHeight,
            child: ClipRect(
              child: OverflowBox(
                alignment: Alignment.center,
                // 按容器比例和相机比例的较大值做缩放,保证铺满容器
                child: FittedBox(
                  fit: BoxFit.cover,
                  child: SizedBox(
                    width: screenWidth,
                    height: screenWidth / _cameraAspectRatio!,
                    child: CameraPreview(controller!),
                  ),
                ),
              ),
            ),
          ),
          // 其他页面内容可以加在这里
          Expanded(child: Container(color: Colors.white)),
        ],
      ),
    );
  }
}

关键适配逻辑说明

  • 首先获取相机原生的宽高比,竖屏使用时要将相机返回的横屏比例反转,避免比例计算错误
  • 用SizedBox严格限定容器尺寸为宽度全屏、高度255
  • 通过FittedBox搭配BoxFit.cover让相机预览按比例铺满容器,超出容器的部分用ClipRect裁切掉,不会出现拉伸变形
  • 如果不需要裁切、可以接受上下留黑边,把BoxFit.cover改成BoxFit.contain即可

注意事项

  • 建议不要使用ResolutionPreset.max,过高的分辨率会大幅增加性能损耗,普通场景下ResolutionPreset.high或者ResolutionPreset.medium完全够用
  • 如果你的应用支持横竖屏切换,需要添加屏幕方向监听,动态调整宽高比的计算逻辑
  • 部分老旧设备可能存在相机比例兼容问题,可以加异常捕获兜底,比例计算失败时默认使用16:9的通用比例

内容的提问来源于stack exchange,提问作者eno2

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 07:15:04