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 状态栏图标/文字为 白色(适合深色背景)
相关推荐
常利兵2 小时前
Android内存泄漏:成因剖析与高效排查实战指南
android
·云扬·2 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
野生技术架构师3 小时前
SQL语句性能优化分析及解决方案
android·sql·性能优化
ZH15455891313 小时前
Flutter for OpenHarmony Python学习助手实战:API接口开发的实现
python·学习·flutter
一只大侠的侠3 小时前
Flutter开源鸿蒙跨平台训练营 Day11从零开发商品详情页面
flutter·开源·harmonyos
一只大侠的侠3 小时前
React Native开源鸿蒙跨平台训练营 Day18自定义useForm表单管理实战实现
flutter·开源·harmonyos
一只大侠的侠3 小时前
React Native开源鸿蒙跨平台训练营 Day20自定义 useValidator 实现高性能表单验证
flutter·开源·harmonyos
renke33643 小时前
Flutter for OpenHarmony:节奏方块 - 基于时间同步与连击机制的实时音乐游戏系统设计
flutter·游戏
晚霞的不甘4 小时前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频
doupoa4 小时前
内存指针是什么?为什么指针还要有偏移量?
android·c++