Flutter进阶(3):屏幕和字体适配专家(ScreenUtil)

fengMisaka / 2024-10-23 / 原文

一、简介

flutter_screenutil 是一个适配屏幕尺寸和屏幕密度的 Flutter 插件。它可以帮助开发者确保 Flutter 应用在不同屏幕尺寸和分辨率的设备上都能保持合理的布局和尺寸。当开发跨多种设备(如不同尺寸的智能手机和平板电脑)的 Flutter 应用时,flutter_screenutil 尤其有用。

二、主要功能

  • 尺寸适配: 允许你根据设计稿的尺寸来设置元素的宽度、高度、字体大小等,插件会自动根据当前设备屏幕的尺寸进行适配。
  • 屏幕密度适配: 自动适配不同的屏幕密度,提供更加清晰的字体和图像。

三、如何使用Flutter ScreenUtil

(1)添加依赖

在 Flutter 项目的 pubspec.yaml 文件中添加 flutter_screenutil 包的依赖:

dependencies:
  flutter_screenutil: ^最新版本号

然后运行 flutter pub get 来安装包。

如果不知道最新版本号,可以先设置为^1.0.0,然后在终端运行 flutter pub get,返回消息会告知你版本号的:

Resolving dependencies... 
The current Dart SDK version is 3.5.1.

Because custom depends on flutter_screenutil >=0.2.1 <5.0.0-nullsafety.0 which doesn't support null safety, version solving failed.

The lower bound of "sdk: '>=2.0.0-dev.68.0 <3.0.0'" must be 2.12.0 or higher to enable null safety.
For details, see https://dart.dev/null-safety


You can try the following suggestion to make the pubspec resolve:
* Try upgrading your constraint on flutter_screenutil: flutter pub add flutter_screenutil:^5.9.3

这里就告知你版本号为5.9.3**,修改**最新版本号**为**5.9.3,然后运行命令:

flutter pub add flutter_screenutil:^5.9.3

最后在运行命令,即可安装好插件:

flutter pub get

(2)导入插件

在你的 Dart 文件中导入 flutter_screenutil 插件:

import 'package:flutter_screenutil/flutter_screenutil.dart';

(3)初始化ScreenUtil

在应用的入口或 MaterialApp 的 builder 中初始化 ScreenUtil,并设置设计稿的尺寸:

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(360, 690), // 设置设计稿的尺寸
      builder: (_, child) => MaterialApp(
        title: 'Flutter ScreenUtil Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: HomePage(),
      ),
    );
  }
}

然后,在你的 UI 代码中,使用 ScreenUtil 类提供的方法设置尺寸和字体大小:

class HomePage extends StatelessWidget {
  const HomePage({super.key});
  @override
  Widget build(BuildContext context) {
    // 初始化ScreenUtil
    ScreenUtil.init(context, designSize: const Size(360, 690));

    return Scaffold(
      appBar: AppBar(
        title: Text(
          'ScreenUtil Demo',
          style: TextStyle(
            fontSize: 20.sp, // 使用 '.sp' 来设置字体大小
          ),
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'This is a text',
              style: TextStyle(
                fontSize: 24.sp, // 为文字大小使用 'sp'
              ),
            ),
            SizedBox(height: 12.h), // 在高度上使用 '.h'
            Container(
              width: 180.w, // 在宽度上使用 '.w'
              height: 200.h, // 在高度上使用 '.h'
              color: Colors.blue,
              child: Text(
                'This box will adapt to the screen width!',
                style: TextStyle(fontSize: 16.sp),
                textAlign: TextAlign.center,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

在上面的代码示例中:

  • ScreenUtil.init 方法设置了设计稿尺寸(设计时指定的屏幕尺寸)。这应该是你一开始就调用的,以便 ScreenUtil 可以使用这些信息进行适配。
  • sp 单位用来确保文字大小在不同设备上看起来相同。它会考虑设备的文字缩放设置。
  • wh 单位用来按设计稿的尺寸进行宽度和高度的适配。

使用 flutter_screenutil 插件时需要注意的是,使用它设置的尺寸是在运行时计算的,它们会根据实际设备屏幕的尺寸和密度与设计稿之间的比例进行调整。但并不是所有的 UI 元素都需要使用 flutter_screenutil 进行适配,有时候简单的 flex 布局或者媒体查询(MediaQuery)可能就足够了。适配屏幕大小主要是为了保持布局在不同大小和分辨率的设备上的一致性。例如,对于较为复杂的布局或是具体的定制化设计,使用 flutter_screenutil 可以确保元素的大小更加精确地反映设计师的意图。


(4)使用ScreenUtil进行适配

适配屏幕宽高

// Container容器的大小就可以与屏幕宽高自适应
Container(
  width: ScreenUtil().setWidth(100), // 根据屏幕宽度适配
  height: ScreenUtil().setHeight(20), // 根据屏幕高度适配
)

适配字体大小

Text(
  'Hello, ScreenUtil',
  style: TextStyle(fontSize: ScreenUtil().setSp(28)), // 根据字体大小适配
)

(5)启用或禁用适配

可以全局或局部启用/禁用宽高和字体的适配:

ScreenUtilInit(
  enableScaleWH: false, // 禁用宽高适配
  enableScaleText: false, // 禁用字体适配
  // ...
)

(6)适配不同方向的屏幕

ScreenUtil 支持横竖屏方向的适配,可以根据不同方向的屏幕尺寸进行适配。


(7)测试Widget

在使用 ScreenUtil 的 widge t测试时,确保使用 tester.pumpAndSettle() 来等待动画或变化完成。

testWidgets('Should ensure widgets settle correctly', (WidgetTester tester) async {
  await tester.pumpWidget(
    const MaterialApp(
      home: ScreenUtilInit(
        child: MyApp(),
      ),
    ),
  );
  await tester.pumpAndSettle(); // 等待动画或变化完成
  // 继续进行断言和测试
});

(8)高级配置

ScreenUtil 提供了多种配置选项,包括但不限于:

  • minTextAdapt:是否根据屏幕宽高的最小值来适配文本。
  • splitScreenMode:是否支持分屏模式。
  • context:提供 BuildContext 以获取物理设备数据。
  • fontSizeResolver:自定义字体大小的适配逻辑。

四、使用建议:

  • 设计稿尺寸:在使用 ScreenUtilInit 初始化时设置的设计尺寸应该是 UI 设计师提供的原始设计稿的尺寸(通常以像素为单位)。这将确保在不同屏幕上的尺寸比例根据设计稿来适配。
  • 布局时使用:布局构建时使用 .w.h 做宽高适配,.sp 做不随系统字体缩放变化的字体大小适配。这样可以最大限度确保在不同屏幕尺寸的设备上,UI 组件保持相同的视觉比例。
  • 测试不同设备:即使使用了 flutter_screenutil,也应该在各种屏幕尺寸和分辨率的设备上测试你的应用,确保布局看起来正确并且美观。
  • 不是银弹:虽然 flutter_screenutil 在处理尺寸适配方面很方便,但它并不适用于所有的布局场景。例如,某些响应式布局可能更适合使用媒体查询 (MediaQuery) 或者 Flex 相关的 widgets

最后,请记住,在定义布局时仍应遵循好的布局实践,如合理使用间距、边距、对齐等,并结合 flutter_screenutil 以达到跨设备一致的用户体验。

五、结论

flutter_screenutil 是一个强大的工具,用于确保Flutter应用在不同设备上具有一致的布局和字体大小。通过本文的指南,你应该能够了解如何在Flutter项目中使用 flutter_screenutil 插件来实现屏幕和字体的适配。如果在实际使用中遇到问题,可以查阅 flutter_screenutil的官方文档 或访问 GitHub仓库 获取更多帮助。