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

Flutter竖屏应用中如何旋转CachedNetworkImage适配全屏?

解决竖屏Flutter应用中横图全屏适配的旋转方案

核心思路

先判断图片是否为横图(宽度>高度),如果是,将图片旋转90度,同时调整父容器的尺寸,让旋转后的图片刚好填满竖屏全屏空间,既避免裁剪也不会出现大量空白,同时保留CachedNetworkImage的缓存和加载状态处理。

具体实现方案

方案一:精准判断图片尺寸后旋转(推荐)

通过异步获取图片原始宽高,精准判断是否需要旋转,适配所有图片比例场景:

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

class FullScreenRotatedImage extends StatefulWidget {
  final String imageUrl;

  const FullScreenRotatedImage({super.key, required this.imageUrl});

  @override
  State<FullScreenRotatedImage> createState() => _FullScreenRotatedImageState();
}

class _FullScreenRotatedImageState extends State<FullScreenRotatedImage> {
  bool _isLandscapeImage = false;
  bool _isLoading = true;

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

  Future<void> _checkImageOrientation() async {
    final imageProvider = CachedNetworkImageProvider(widget.imageUrl);
    final imageStream = imageProvider.resolve(const ImageConfiguration());
    final completer = Completer<ImageInfo>();
    final listener = ImageStreamListener((info, sync) {
      if (!completer.isCompleted) completer.complete(info);
    });
    imageStream.addListener(listener);

    final imageInfo = await completer.future;
    imageStream.removeListener(listener);

    setState(() {
      _isLandscapeImage = imageInfo.image.width > imageInfo.image.height;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    final screenSize = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.black,
      body: _isLoading
          ? const Center(child: CircularProgressIndicator(color: Colors.white))
          : Center(
              child: _isLandscapeImage
                  ? Transform.rotate(
                      angle: 3.1415926 / 2, // 90度转弧度
                      child: SizedBox(
                        width: screenSize.height, // 旋转后宽度对应屏幕高度
                        height: screenSize.width, // 旋转后高度对应屏幕宽度
                        child: CachedNetworkImage(
                          imageUrl: widget.imageUrl,
                          fit: BoxFit.cover,
                          placeholder: (context, url) => const Center(child: CircularProgressIndicator(color: Colors.white)),
                          errorWidget: (context, url, error) => const Icon(Icons.error, color: Colors.white),
                        ),
                      ),
                    )
                  : SizedBox(
                      width: screenSize.width,
                      height: screenSize.height,
                      child: CachedNetworkImage(
                        imageUrl: widget.imageUrl,
                        fit: BoxFit.cover,
                        placeholder: (context, url) => const Center(child: CircularProgressIndicator(color: Colors.white)),
                        errorWidget: (context, url, error) => const Icon(Icons.error, color: Colors.white),
                      ),
                    ),
            ),
    );
  }
}

// 使用示例
// Navigator.push(context, MaterialPageRoute(builder: (_) => FullScreenRotatedImage(imageUrl: "你的图片URL")));

方案二:简化判断(无需提前加载图片)

如果不需要精准适配所有比例,可直接通过屏幕宽高比判断,代码更简洁:

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

class FullScreenRotatedImage extends StatelessWidget {
  final String imageUrl;

  const FullScreenRotatedImage({super.key, required this.imageUrl});

  @override
  Widget build(BuildContext context) {
    final screenSize = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.black,
      body: Center(
        child: LayoutBuilder(
          builder: (context, constraints) {
            // 竖屏场景下,图片宽>高则判定为横图
            final isLandscapeImage = screenSize.width / screenSize.height < 1;
            return isLandscapeImage
                ? Transform.rotate(
                    angle: 3.1415926 / 2,
                    child: SizedBox(
                      width: constraints.maxHeight,
                      height: constraints.maxWidth,
                      child: CachedNetworkImage(
                        imageUrl: imageUrl,
                        fit: BoxFit.cover,
                        placeholder: (context, url) => const CircularProgressIndicator(color: Colors.white),
                        errorWidget: (context, url, error) => const Icon(Icons.error, color: Colors.white),
                      ),
                    ),
                  )
                : CachedNetworkImage(
                    imageUrl: imageUrl,
                    fit: BoxFit.cover,
                    placeholder: (context, url) => const CircularProgressIndicator(color: Colors.white),
                    errorWidget: (context, url, error) => const Icon(Icons.error, color: Colors.white),
                  );
          },
        ),
      ),
    );
  }
}

关键细节说明

  • 旋转角度转换:Transform.rotate接受弧度值,90度对应π/2(即3.1415926/2)。
  • 尺寸适配:横图旋转后宽高逻辑互换,所以容器宽高要设置为屏幕的高和宽,确保旋转后图片刚好填满竖屏。
  • 状态处理:保留CachedNetworkImage的加载、错误状态提示,避免用户感知异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:20:30