Flutter的屏幕适配

使用Flutter开发商用项目,则你必不可少要考虑的一个东西,那就是屏幕适配。回顾一下Android的屏幕适配方案,有以下考虑。

  1. dp替换px
  2. fragment适配平板以及使用不同分辨率的布局
  3. 百分比布局与动态计算控件尺寸

那么Flutter也可以借鉴Android原生的思路。

  1. 使用flutter_screenutil库,得到考虑分辨率后的单位
  2. 自适应和动态计算组件大小

适配布局尺寸

如果有设计稿的情况下,适配就变得简单了,建议直接用 flutter_screenutil,方便快捷。

使用 flutter_screenutil 适配

首先在pubspec.yaml文件中安装依赖。

yaml 复制代码
dependencies:
  flutter_screenutil: ^5.6.0

接下来在main.dart中初始化尺寸。

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(375, 812), // 你的设计稿尺寸,例如 iPhone X
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (context, child) {
        return MaterialApp(
          home: const HomePage(),
        );
      },
    );
  }
}

最后我们只要按照它的使用方式使用就行了。即所有尺寸都加 .w.h.r.sp等。比如 设计稿是375x812,宽度标的10,那么你就写10.w,高度标的15,那么你就写15.h,对于圆角半径,你就写比如5.r。sp就跟Android原生类似了,不做过多赘述。

误区

对于r的计算方式,刚接触的可能会想当然的认为是宽和高的平均值。看了源码发现实际上不是,它是取的宽度和高度的较小值确认缩放比例的。通常用于半径、边框宽度这种不太区分是宽还是高的场景。

使用媒体查询计算缩放因子

也可以自己动态计算缩放的比例,这种方式麻烦一些,你只需要知道有这种方式即可。

dart 复制代码
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
double scaleWidth(double width) => width * screenWidth / 375.0;
需要注意的地方

在Android中,如果是自己计算,通常还需要考虑系统状态栏和导航栏对布局的影响。

dart 复制代码
// 获取系统状态栏的高度
double statusBarHeight = MediaQuery.of(context).padding.top;
// 获取系统导航栏的高度
double navigationBarHeight = MediaQuery.of(context).padding.bottom;

如果你用的是 Scaffold,并且开启了 resizeToAvoidBottomInset: true,它会在键盘弹出时,自动调整布局,TextField会向上推移,避免被键盘遮挡。并且默认它会占据状态栏进行布局,比如你不想做沉浸式,你需要使用SafeArea组件包裹,这样你的布局就会避开状态栏了。

dart 复制代码
SafeArea(
  child: Scaffold(
    appBar: AppBar(title: Text("My App")),
    body: Column(
      children: [
        Text('This is a safe area'),
        // 更多内容
      ],
    ),
  ),
)

设置布局方向

使用SystemChrome.setPreferredOrientations可以设置布局的屏幕方向。例如:

dart 复制代码
SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
  DeviceOrientation.landscapeLeft,
  // ...
]);

只允许竖屏(正向)

dart 复制代码
SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
]);

只允许横屏(向左)

dart 复制代码
SystemChrome.setPreferredOrientations([
  DeviceOrientation.landscapeLeft,
]);

支持竖屏正向 & 横屏

dart 复制代码
SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
  DeviceOrientation.landscapeLeft,
  DeviceOrientation.landscapeRight,
]);
需要注意的地方

如果你在main函数里面设置,你需要加async关键字,并在调用SystemChrome.setPreferredOrientations()之前先调用WidgetsFlutterBinding.ensureInitialized()以确保初始化完成。

dart 复制代码
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp, // 只竖屏
  ]);
  runApp(MyApp());
}

否则你会遇到以下错误。

Binding has not yet been initialized

适配状态栏图标和文字颜色

这个功能在Android6.0开始支持,请参见公主。哦,不对,请参考我的开源库Dora 的源代码github.com/dora4/dora/...

dart 复制代码
return AnnotatedRegion<SystemUiOverlayStyle>(
  value: SystemUiOverlayStyle.dark, // 或 light
  child: Scaffold(
    backgroundColor: Colors.white,
    body: YourPage(),
  ),
);
样式 效果
SystemUiOverlayStyle.dark 状态栏图标/文字为 黑色(适合浅色背景)
SystemUiOverlayStyle.light 状态栏图标/文字为 白色(适合深色背景)
相关推荐
一起养小猫9 小时前
Flutter for OpenHarmony 进阶:体育计分系统与数据持久化深度解析
flutter·harmonyos
ujainu9 小时前
Flutter + OpenHarmony 游戏开发进阶:主菜单架构与历史最高分持久化
flutter·游戏·架构·openharmony
STCNXPARM10 小时前
Linux camera之V4L2子系统详解
android·linux·camera·v4l2架构
铅笔侠_小龙虾10 小时前
Flutter Demo
开发语言·javascript·flutter
2501_9445255410 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 账户详情页面
android·java·开发语言·前端·javascript·flutter
2601_9498574310 小时前
Flutter for OpenHarmony Web开发助手App实战:快捷键参考
前端·flutter
mocoding12 小时前
flutter通信小能手pigeon三方库已完成鸿蒙化适配
flutter·华为·harmonyos
一起养小猫12 小时前
Flutter for OpenHarmony 实战:2048游戏完整开发指南
flutter·游戏·harmonyos
不急不躁12314 小时前
Android16 GTS GtsPermissionTestcases 测试,跳过权限检查
android
血色橄榄枝14 小时前
13-14 底部选项卡 flutter on openHarmony
flutter·开源·鸿蒙