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
相关产品推荐
相关产品推荐

