Flutter屏幕适配指南

Flutter中尺寸的单位

Flutter 尺寸单位采用的是 逻辑像素 ,类似于 iOS 中的 pt 、Android 中的 dp

概念对比

分类 说明
逻辑像素 也被称为"与设备或分辨率无关的像素"。
物理像素 也称"设备像素",是屏幕的基础单位,也是我们能看到的尺寸。 示例:iPhone 6 的屏幕宽度方向有 750 个像素点 ,高度方向有 1334 个像素点

Flutter 使用逻辑像素作为布局单位。逻辑像素 = 物理像素 px / devicePixelRatio

在 Flutter 中,devicePixelRatioui.Window 类提供。
Window 是 Flutter Framework 连接宿主操作系统的接口,因此 devicePixelRatio 属性是引擎层从原生平台获取的。

  • Android 中对应 density
  • iOS 中对应 [UIScreen mainScreen].scale

相同逻辑像素在不同分辨率手机上看到的物理像素不同,原因是每个设备可能都会有不同的 dpr(devicePixelRatio)。

一个简单的适配工具类

我们的核心目标是让设计稿里的"100 × 100"之类的尺寸,在各种尺寸、分辨率的设备上得到"视觉上占屏幕宽度(或高度)的相同比例"

核心思路

  1. 以设计稿宽度为基准,计算设备宽度的缩放比(ratio)。
  2. 所有 UI 尺寸乘以 ratio 后再绘制,实现跨分辨率"看起来一致"。
  3. 借助 Dart 扩展方法 (extension) 把 xx.px 写法变成语法糖,降低适配成本。
dart 复制代码
import 'package:flutter/cupertino.dart';

/// =======================
/// Int 类型扩展 ------ 语法糖
/// =======================
/// 让数值直接写成 `200.px` 即可自动适配
extension IntFix on int {
  /// 示例:`200.px`
  /// 将 int 转为 double 再送给 ScreenHelper 计算
  double get px => ScreenHelper.getPx(toDouble());
}

/// =======================
/// double 类型扩展 ------ 语法糖
/// =======================
/// 让小数也能写成 `200.0.px`
extension DoubleFix on double {
  /// 示例:`200.0.px`
  double get px => ScreenHelper.getPx(this);
}

/// =======================================
/// ScreenHelper ------ 屏幕适配核心工具类
/// =======================================
class ScreenHelper {
  /// 设备屏幕信息
  static late MediaQueryData _mediaQueryData;

  /// 设备屏幕宽高(逻辑像素)
  static late double screenWith;   // 当前设备宽度
  static late double screenHeight; // 当前设备高度

  /// 设计稿基准宽度与设备宽度的缩放比
  static late double ratio;

  /// ------------------------------------------------
  /// 初始化:在 APP 启动的首个页面调用
  /// 例如:ScreenHelper.init(context, baseWidth: 375);
  ///
  /// @param context   BuildContext,用于获取 MediaQuery
  /// @param baseWidth UI 设计稿的宽度(假设默认 375)
  /// ------------------------------------------------
  static void init(BuildContext context, {double baseWidth = 375}) {
    _mediaQueryData = MediaQuery.of(context);

    screenWith   = _mediaQueryData.size.width;  // 设备实际宽度
    screenHeight = _mediaQueryData.size.height; // 设备实际高度

    // 计算缩放比:设备宽 ÷ 设计稿宽
    ratio = screenWith / baseWidth;
  }

  /// ------------------------------------------------
  /// 将"设计稿尺寸"转换为当前设备应显示的逻辑像素
  ///
  /// 使用方式:`50.px` 或 `ScreenHelper.getPx(50)`
  /// ------------------------------------------------
  static double getPx(double size) => ratio * size;
}

使用示例

arduino 复制代码
dart
@override
Widget build(BuildContext context) {
  // 只需在应用入口或首个页面初始化一次
  ScreenHelper.init(context, baseWidth: 375);

  return Container(
    width: 200.px,   // 自动按比例适配
    height: 200.px,
    color: Colors.blue,
  );
}
相关推荐
灵感__idea5 小时前
JavaScript高级程序设计(第5版):好的编程就是掌控感
前端·javascript·程序员
烛阴6 小时前
Mix
前端·webgl
代码续发6 小时前
前端组件梳理
前端
试图让你心动7 小时前
原生input添加删除图标类似vue里面移入显示删除[jquery]
前端·vue.js·jquery
陈不知代码7 小时前
uniapp创建vue3+ts+pinia+sass项目
前端·uni-app·sass
小王码农记7 小时前
sass中@mixin与 @include
前端·sass
陈琦鹏7 小时前
轻松管理 WebSocket 连接!easy-websocket-client
前端·vue.js·websocket
hui函数8 小时前
掌握JavaScript函数封装与作用域
前端·javascript
行板Andante8 小时前
前端设计中如何在鼠标悬浮时同步修改块内样式
前端
Carlos_sam8 小时前
Opnelayers:ol-wind之Field 类属性和方法详解
前端·javascript