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

Flutter中基于Getx的响应式UI无法随屏幕尺寸动态更新

问题解决:Getx实现动态响应式尺寸适配

原问题中,Dimensions类的静态变量仅在初始化时获取一次屏幕尺寸,横竖屏切换或窗口缩放时无法更新,导致UI不能自适应。下面给出两种解决方案,既保留原有的简洁调用方式,又实现尺寸动态更新。

方案一:使用Getx控制器监听屏幕变化

步骤1:创建尺寸管理控制器

import 'package:get/get.dart';

class DimensionsController extends GetxController {
  RxDouble screenHeight = Get.context!.height.obs;
  RxDouble screenWidth = Get.context!.width.obs;

  @override
  void onInit() {
    super.onInit();
    // 监听屏幕尺寸变化,自动更新响应式变量
    ever(Get.mediaQuery, (MediaQueryData mediaQuery) {
      screenHeight.value = mediaQuery.size.height;
      screenWidth.value = mediaQuery.size.width;
    });
  }

  // 所有尺寸改为getter,每次访问都会基于最新屏幕尺寸计算
  double get pageView => screenHeight.value / 2.64;
  double get pageViewContainer => screenHeight.value / 3.84;
  double get pageTextContainer => screenHeight.value / 7.03;

  // 高度相关
  double get height10 => screenHeight.value / 84.4;
  double get height15 => screenHeight.value / 56.27;
  double get height20 => screenHeight.value / 42.2;
  double get height45 => screenHeight.value / 18.76;
  double get height30 => screenHeight.value / 28.13;

  // 宽度相关
  double get width10 => screenHeight.value / 84.4;
  double get width15 => screenHeight.value / 56.27;
  double get width20 => screenHeight.value / 42.2;
  double get width30 => screenHeight.value / 28.13;
  double get width45 => screenHeight.value / 18.76;

  // 字体大小
  double get font20 => screenHeight.value / 42.2;
  double get font26 => screenHeight.value / 42.2;
  double get font16 => screenHeight.value / 52.75;

  // 圆角
  double get radius15 => screenHeight.value / 56.27;
  double get radius20 => screenHeight.value / 42.2;
  double get radius30 => screenHeight.value / 28.13;

  // 图标大小
  double get iconSize24 => screenHeight.value / 35.17;
  double get iconSize16 => screenHeight.value / 52.75;

  // ListView尺寸
  double get listViewImageSize => screenWidth.value / 3.25;
  double get listViewTextSize => screenWidth.value / 3.9;

  // 美食详情页尺寸
  double get foodImageSize => screenHeight.value / 2.41;

  // 底部导航栏高度
  double get bottomHeightBar => screenHeight.value / 6.25;

  // 启动页图片尺寸
  double get splashImg => screenHeight.value / 3.375;
}

步骤2:初始化控制器

在App入口处初始化控制器,确保全局可用:

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    Get.put(DimensionsController()); // 初始化尺寸控制器
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

步骤3:简化调用(可选)

如果想保留原有的Dimensions.xxx调用方式,创建一个封装类:

class Dimensions {
  static DimensionsController get _controller => Get.find<DimensionsController>();

  static double get pageView => _controller.pageView;
  static double get pageViewContainer => _controller.pageViewContainer;
  static double get pageTextContainer => _controller.pageTextContainer;

  static double get height10 => _controller.height10;
  static double get height15 => _controller.height15;
  static double get height20 => _controller.height20;
  static double get height45 => _controller.height45;
  static double get height30 => _controller.height30;

  static double get width10 => _controller.width10;
  static double get width15 => _controller.width15;
  static double get width20 => _controller.width20;
  static double get width30 => _controller.width30;
  static double get width45 => _controller.width45;

  static double get font20 => _controller.font20;
  static double get font26 => _controller.font26;
  static double get font16 => _controller.font16;

  static double get radius15 => _controller.radius15;
  static double get radius20 => _controller.radius20;
  static double get radius30 => _controller.radius30;

  static double get iconSize24 => _controller.iconSize24;
  static double get iconSize16 => _controller.iconSize16;

  static double get listViewImageSize => _controller.listViewImageSize;
  static double get listViewTextSize => _controller.listViewTextSize;

  static double get foodImageSize => _controller.foodImageSize;
  static double get bottomHeightBar => _controller.bottomHeightBar;
  static double get splashImg => _controller.splashImg;
}

使用方式

和原代码完全一致,无需修改现有UI代码:

SizedBox(
  width: Dimensions.width10,
),

核心原理

  1. 使用RxDouble响应式变量存储屏幕尺寸,值变化时自动通知依赖的UI组件重建
  2. 通过ever(Get.mediaQuery, ...)监听系统媒体查询的变化,实时更新屏幕尺寸值
  3. 所有尺寸参数改为getter方法,每次访问都会基于最新的屏幕尺寸计算,保证数值动态性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 01:39:53