如何制作适配设备且旋转不失效的Flutter响应式Widget?
解决Flutter响应式Widget的设备类型误判与sizer包初始化问题
一、修复sizer包的初始化错误
你遇到的LateInitializationError: Field 'deviceType' has not been initialized是因为未正确初始化sizer包。sizer要求必须在根组件(通常是MaterialApp/CupertinoApp)外层包裹Sizer组件,示例如下:
import 'package:flutter/material.dart'; import 'package:sizer/sizer.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return Sizer( // 必须添加该包裹层完成初始化 builder: (context, orientation, deviceType) { return MaterialApp( title: 'Responsive Demo', home: YourHomePage(), ); }, ); } }
二、修正响应式Widget的逻辑错误
原代码中isDesktop的条件存在逻辑错误(误将DeviceType.desktop写为DeviceType.tablet),同时我们可以结合sizer的DeviceType(基于物理设备类型,屏幕旋转不会改变)来解决手机旋转误判为平板的问题。重构后的代码如下:
import 'package:flutter/material.dart'; import 'package:sizer/sizer.dart'; class Responsive extends StatelessWidget { const Responsive({ required this.mobile, required this.tablet, required this.desktop, super.key, }); final Widget mobile; final Widget tablet; final Widget desktop; // 物理设备类型+屏幕宽度双重判断,避免旋转误判 static bool isMobile(BuildContext context) => SizerUtil.deviceType == DeviceType.mobile && MediaQuery.of(context).size.width < 600; static bool isTablet(BuildContext context) => SizerUtil.deviceType == DeviceType.tablet || (SizerUtil.deviceType == DeviceType.mobile && MediaQuery.of(context).size.width >= 600); static bool isDesktop(BuildContext context) => SizerUtil.deviceType == DeviceType.desktop; @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (isDesktop(context)) { return desktop; } else if (isTablet(context)) { return tablet; } else { return mobile; } }, ); } }
三、使用示例
在页面中调用Responsive组件,传入不同设备的UI实现:
class YourHomePage extends StatelessWidget { const YourHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Responsive( mobile: MobileUI(), tablet: TabletUI(), desktop: DesktopUI(), ), ); } } // 示例UI组件 class MobileUI extends StatelessWidget { @override Widget build(BuildContext context) => const Center(child: Text('Mobile UI')); } class TabletUI extends StatelessWidget { @override Widget build(BuildContext context) => const Center(child: Text('Tablet UI')); } class DesktopUI extends StatelessWidget { @override Widget build(BuildContext context) => const Center(child: Text('Desktop UI')); }
核心优势
- 基于物理设备类型判断,手机旋转时不会改变设备类型,彻底解决旋转误判问题
- 结合屏幕宽度二次校验,适配极端场景下的UI展示
- 代码逻辑清晰,便于后续维护和扩展
内容的提问来源于stack exchange,提问作者My Car
相关产品推荐
相关产品推荐

