網站首頁 編程語言 正文
因移動設備的多樣性,特別是 Android 的碎片化嚴重,存在各種各樣的分辨率,而 Flutter 跨平臺開發又需同時支持 Android 和 iOS ,為盡可能的還原設計圖效果提升用戶體驗,屏幕適配就勢在必行了。
Flutter 暫時沒有官方的屏幕適配方案,在 Flutter 項目開發中目前大部分的適配方案都是通過比例來進行適配,是一個通用的適配方法,該適配方法也在前端、Android、iOS、小程序等開發中廣泛使用。
原理
UI 設計的時候一般會按照一個固定的尺寸進行設計,如 360 x 690
,實際設備分辨率可能是 Google Pixel: 1080 x 1920
、Google Pixel XL: 1440 x 2560
、iPhone 12 Pro Max: 1284 x 2778
等等。開發時如果直接按照設計圖寫死數值則會出現最后實現的效果跟設計效果不一致的情況。這個時候就可以用比例的方式來進行適配。
將設計圖分為固定單位并給這個單位定義一個標識,例如就叫 w
,然后通過獲取設備分辨率,使用設備真實寬度除以設計圖寬度 ,就得到了 1w
代表的真實寬度:
1w = 設備真實寬度 / 設計圖寬度
如設計圖尺寸是 360 x 690
,則寬度為 360w
,真實設備寬度為 1080 則 1w = 1080 / 360 = 3
。
根據上面的算法,得到對應設備的 1w
的真實寬度:
Google Pixel: 1w = 1080 / 360 = 3
Google Pixel XL: 1w = 1440 / 360 = 4
iPhone 12 Pro Max: 1w = 1284 / 360 = 3.57
按照同樣的算法,可以給高度定義一個單位為 h
, 得出對應設備的高度單位的真實值,如下:
Google Pixel: 1h = 1920 / 690 = 2.78
Google Pixel XL: 1h = 2560 / 690 = 3.71
iPhone 12 Pro Max: 1h = 2778 / 690 = 4.03
得到換算以后 w
、h
的真實值以后,開發過程中就可以使用其來設置 UI 控件的高、寬、間距等,使其最終呈現的效果無限接近設計圖的效果。
開發過程中一般采用寬度來進行適配,控件高度要么自適應,要么也設置寬度的單位,然后整體高度根據內容自適應。但是如果有特殊需求也可以使用高度來進行適配,比如需求要求是 banner 占屏幕的 1/4 ,或者要求內容剛好一屏顯示,這個時候設置控件的高度時就可以采用高度單位來進行適配。
基于上面的算法,在項目中就可以實現對應的適配方案了,但本著不重復造輪子的思想,項目開發中可以直接使用 flutter_screenutil 這個適配庫。
flutter_screenutil
flutter_screenutil
就是基于上述比例適配原理而實現的屏幕適配庫。 目前最新版本是 5.0.1,在 GitHub 上擁有 2.8k 的 star 。在 pub.dev 上擁有1536 個 like ,130 的 pub 指數, 99% 的人氣,說明這是一個靠譜的輪子。
flutter_screenutil:讓你的UI在不同尺寸的屏幕上都能顯示合理的布局!
添加依賴
在項目根目錄的 pubspec.yaml
中添加 flutter_screenutil
的依賴:
dependencies: flutter: sdk: flutter # 添加依賴 flutter_screenutil: ^5.0.1
初始化
flutter_screenutil
提供了兩種方式進行初始化:ScreenUtilInit
方式和 ScreenUtil.init
方式。首先在使用的地方導入包:
import 'package:flutter_screenutil/flutter_screenutil.dart';
ScreenUtilInit
使用 ScreenUtilInit 方式進行初始化,需要將項目的 MaterialApp 進行一層包裹,然后在 builder
中返回項目本身的 MaterialApp ,在 ScreenUtilInit 的 designSize
參數中傳入設計圖的尺寸,實現如下:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ScreenUtilInit( designSize: Size(360, 690), //傳入設計圖尺寸 builder: () => MaterialApp( ... ), ); } }
ScreenUtil.init
直接使用 ScreenUtil.init
方法,傳入屏幕尺寸、設計圖尺寸和屏幕方向即可對 flutter_screenutil
進行初始化,代碼如下:
ScreenUtil.init( BoxConstraints( maxWidth: MediaQuery.of(context).size.width, //屏幕寬度 maxHeight: MediaQuery.of(context).size.height, //屏幕高度 ), designSize: const Size(360, 690), // 設計圖尺寸 orientation: Orientation.portrait); // 屏幕方向
使用這種方式只需在使用 flutter_screenutil
前進行初始化即可,一般放在根路由即第一個頁面加載的時候進行初始化。
注意:ScreenUtil.init
不能在 MyApp
中進行初始化,會報如下錯誤 No MediaQuery ancestor could be found starting from the context that was passed to MediaQuery.of(). This can happen because you have not added a WidgetsApp, CupertinoApp, or MaterialApp widget (those widgets introduce a MediaQuery), or it can happen if the context you use comes from a widget above those widgets.
因為這個時候還沒加載 MaterialApp
無法使用 MediaQuery.of(context ) 獲取到屏幕寬高
關于上面兩種初始化方法,flutter_screenutil
作者推薦使用第二種方式。
使用
初始化以后就可以使用 flutter_screenutil
提供的方法獲取到適配后的數值進行使用了。
可通過如下 api 獲取寬高以及字體的適配數值:
ScreenUtil().setWidth(540) //根據屏幕寬度適配尺寸 ScreenUtil().setHeight(200) //根據屏幕高度適配尺寸(一般根據寬度適配即可) ScreenUtil().radius(200) //根據寬度或高度中的較小者進行調整 ScreenUtil().setSp(24) //字體大小適配
傳入的參數即為設計圖上的大小。在實際使用中的示例如下:
Container( width: ScreenUtil().setWidth(200), height: ScreenUtil().setHeight(540), child: Text("Hello", style: TextStyle(fontSize: ScreenUtil().setSp(24)),), );
這樣即可使用適配的數值進行開發。
但發現這樣寫太麻煩了,為了獲取一個適配的數值,要寫一串的很長的代碼。flutter_screenutil
提供了更簡潔的調用方法,使用 Dart 擴展為 num 類型擴展了一系列屬性可以方便開發者調用,上面的 api 可以通過擴展屬性進行如下轉換:
ScreenUtil().setWidth(540) => 540.h ScreenUtil().setHeight(200) => 200.w ScreenUtil().radius(200) => 200.r ScreenUtil().setSp(24) => 24.sp
修改后的使用示例如下:
Container( width: 200.w, height: 540.h, child: Text("Hello", style: TextStyle(fontSize: 24.sp),), );
這樣就簡潔多了。
注意:根據前面講解的適配原理知道,一般情況下 1.w != 1.h
,除非剛好屏幕分辨率比例與設計圖比例一致,所以如果要設置正方形,切記使用相同的單位,如都設置相同的 w 或者 h ,否則可能顯示為長方形。
除了上面 4 種擴展屬性以外,還提供了 sm
以及 sw
、 sh
-
sm
:取數值本身與sp
的值最小的值,如12.sm
則取12
與12.sp
的值進行比較,取最小的值。 -
sw
:screen width 的縮寫,即屏幕寬度,作用是按屏幕寬度比例返回值。如0.2.sw
則返回屏幕寬度的 20%,1.sw
則是整個屏幕寬度 -
sh
:screen height 的縮寫,及屏幕高度,作用與 sw 類似,返回指定比例的屏幕高度值。如1.sh
為整個屏幕高度
使用 sp
作為字體單位,默認是會隨著系統字體縮放進行變化,如果不想字體隨著系統縮放而變化,可設置 textScaleFactor
為 1.0
來實現。項目中可對 MaterialApp
進行全局設置或者對 Text
進行單獨設置:
全局設置:
MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter_ScreenUtil', theme: ThemeData( primarySwatch: Colors.blue, ), builder: (context, widget) { return MediaQuery( ///設置文字大小不隨系統設置改變 data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: widget, ); }, home: HomePage(title: 'FlutterScreenUtil Demo'), ),
Text 單獨設置:
Text("text", textScaleFactor: 1.0)
效果
附上官方效果圖:
其他 Api
除了適配的 api 以外,flutter_screenutil
還提供了很多實用的 api ,如下 :
-
ScreenUtil().pixelRatio
:設備的像素密度 -
ScreenUtil().screenWidth
:屏幕寬度,等同于1.sw
-
ScreenUtil().screenHeight
:屏幕高度,等同于1.sh
-
ScreenUtil().bottomBarHeight
:底部導航高度,如全屏底部按鍵的高度 -
ScreenUtil().statusBarHeight
:狀態欄高度 -
ScreenUtil().textScaleFactor
:系統字體縮放比例 -
ScreenUtil().scaleWidth
:實際寬度與設計圖寬度的比例 -
ScreenUtil().scaleHeight
:實際高度與設計圖高度的比例 -
ScreenUtil().orientation
:屏幕方向
原文鏈接:https://juejin.cn/post/7041021257562718239
相關推薦
- 2022-03-26 Unity實現坦克模型_C#教程
- 2022-06-20 C語言三種方法解決輪轉數組問題_C 語言
- 2022-07-11 Sonatype Nexus搭建Maven私服
- 2022-08-31 C#泛型語法詳解_C#教程
- 2022-12-22 Qt實現繪制一個簡單多邊形的示例代碼_C 語言
- 2022-12-26 C語言實現十六進制轉換為十進制的方法詳解_C 語言
- 2024-01-28 在已有git倉庫的情況下,如何提交修改后的文件
- 2023-07-14 promise封裝的ajax + rem布局
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支