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

如何制作适配设备且旋转不失效的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:45:30