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 状态栏图标/文字为 白色(适合深色背景)
相关推荐
沙振宇31 分钟前
【HarmonyOS】ArkTS开发应用的横竖屏切换
android·华为·harmonyos
橙子199110162 小时前
Kotlin 中的作用域函数
android·开发语言·kotlin
zimoyin2 小时前
Kotlin 懒初始化值
android·开发语言·kotlin
枣伊吕波3 小时前
第六节第二部分:抽象类的应用-模板方法设计模式
android·java·设计模式
萧然CS3 小时前
使用ADB命令操作Android的apk/aab包
android·adb
肥肥呀呀呀6 小时前
在Flutter上如何实现按钮的拖拽效果
前端·javascript·flutter
_extraordinary_7 小时前
MySQL 事务(二)
android·数据库·mysql
鸿蒙布道师11 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
橙子1991101617 小时前
在 Kotlin 中什么是委托属性,简要说说其使用场景和原理
android·开发语言·kotlin
androidwork17 小时前
Kotlin Android LeakCanary内存泄漏检测实战
android·开发语言·kotlin