做移動(dòng)端開發(fā)的同學(xué)都知道,針對(duì)不同型號(hào)和尺寸的手機(jī)要進(jìn)行頁面的適配,且 iOS 和 Android 適配方案各不相同,那我們用 Flutter 開發(fā)要怎么處理屏幕適配呢?
Flutter中的單位
Flutter使用的是類似于iOS中的點(diǎn)pt,也就是point。我們經(jīng)常說 iPhone8 的尺寸是375x667,但是它的分辨率其實(shí)是 750x1334 。因?yàn)閕Phone8的像素比(devicePixelRatio)是2.0,iPhone8plus的像素比是3.0。
iPhone各型號(hào)設(shè)備的尺寸

Flutter 中獲取設(shè)備信息
獲取設(shè)備相關(guān)的信息,可以使用官方提供的一個(gè)庫
device_info: ^2.0.3
//獲取設(shè)備的信息
Future getDeviceInfo() async{
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
var dataInfo;
//判斷是iOS平臺(tái)還是Android平臺(tái)
//IosDeviceInfo里面包含我們常用到的設(shè)備信息
if(Platform.isIOS) {
print('IOS設(shè)備:');
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;dataInfo = iosInfo;
} else if(Platform.isAndroid) {
print('Android設(shè)備');
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;dataInfo = androidInfo;
}
return dataInfo;
}
獲取屏幕的尺寸
需要引入
import'dart:ui';
獲取屏幕的寬高、劉海高度、分辨率等信息
// 1.媒體查詢信息final mediaQueryData = MediaQuery.of(context);
// 2.獲取寬度和高度final screenWidth = mediaQueryData.size.width;
final screenHeight = mediaQueryData.size.height;
final physicalWidth = window.physicalSize.width;
final physicalHeight = window.physicalSize.height;
final dpr = window.devicePixelRatio;
// 3.狀態(tài)欄的高度// 有劉海的屏幕:44 沒有劉海的屏幕為20final statusBarHeight = mediaQueryData.padding.top;
// 有劉海的屏幕:34 沒有劉海的屏幕0final bottomHeight = mediaQueryData.padding.bottom;
print('屏幕width:$screenWidth height:$screenHeight');
print('分辨率: $physicalWidth * $physicalHeight');
print('像素比: $dpr');
print('狀態(tài)欄height: $statusBarHeight 底部高度:$bottomHeight');
打印出的設(shè)備尺寸
Performing hot restart...
Syncing files to device iPhone 12 Pro...
Restarted application in 575ms.
flutter: 屏幕width:390.0 height:844.0
flutter: 分辨率: 1170.0 * 2532.0
flutter: 像素比: 3.0
flutter: 狀態(tài)欄height: 47.0 底部高度:34.0
適配方案
1.通過等比換算的方式
計(jì)算公式:實(shí)際尺寸 = UI尺寸 * 設(shè)備寬度/設(shè)計(jì)圖寬度
這里封裝了一個(gè)類Adapt,通過類可以獲取屏幕的信息
class Adapt {
static double screenWidth = 0;
static double screenHeight = 0;
static double physicalWidth = 0;
static double physicalHeight = 0;
static double dpr = 0;
static double ratio = 1.0;
static double statusBarHeight = 0;
static double bottomHeight = 0;
static void initialize(BuildContext context, {double UIWidth = 375}) {
// 1.媒體查詢信息
final mediaQueryData = MediaQuery.of(context);
// 2.獲取寬度和高度
screenWidth = mediaQueryData.size.width;screenHeight = mediaQueryData.size.height;physicalWidth = window.physicalSize.width;physicalHeight = window.physicalSize.height;
//像素比
dpr = window.devicePixelRatio;
// 3.狀態(tài)欄的高度
// 頂部有劉海:47pt 沒有劉海的屏幕為20pt
statusBarHeight = mediaQueryData.padding.top;
// 底部有劉海:34pt 沒有劉海的屏幕0pt
bottomHeight = mediaQueryData.padding.bottom;
//比例
ratio = screenWidth/UIWidth;
}
static pt(size){
return size * Adapt.ratio;
}
}
示例代碼
UI給出的設(shè)計(jì)稿的尺寸是375*667,定義一個(gè)大小為(300*300)pt的盒子,盒子中顯示字體大小為30pt的文字
@override
Widget build(BuildContext context) {
Adapt.initialize(context);
returnScaffold(
appBar: AppBar(
title: const Text('屏幕適配'),
),
body: Center(
child: Container(
width: Adapt.pt(300),
height: Adapt.pt(300),
color: Colors.orange,
alignment: Alignment.center,
child: Text(
'Hello Word',
style: TextStyle(fontSize: Adapt.pt(30)),
textAlign: TextAlign.center,
),
),
),
);
}
運(yùn)行效果圖,明顯右邊做適配的更符合效果

2. rpx方案適配
rpx是小程序中的適配方案,它將750px作為設(shè)計(jì)稿,1rpx=屏幕寬度/750,其它所有的單位都使用rpx單位。
不管是什么屏幕,統(tǒng)一分成750份
在iPhone8上: 1rpx = 375/750 = 0.5px
在iPhone12proMax 上:1rpx = 428/750 = 0.571px
所以我們就可以通過上面的計(jì)算方式,算出一個(gè)rpx,再將自己的size和rpx單位相乘即可:比如300px的寬度:3002rpx
在iPhone8上計(jì)算出的結(jié)果是300px
在在iPhone12proMax上計(jì)算出的結(jié)果是342.6px通過計(jì)算可以看出,還是有明顯數(shù)據(jù)上的差別的。
這里也是封裝一個(gè)類 Adapt,直接可以獲取屏幕的信息
class Adapt {
static MediaQueryData _mediaQueryData = MediaQueryData();
static double screenWidth = 0;
static double screenHeight = 0;
static double rpx = 0;
static double px = 0;
static void initialize(BuildContext context, {double standardWidth = 750}) {
_mediaQueryData = MediaQuery.of(context);screenWidth = _mediaQueryData.size.width;screenHeight = _mediaQueryData.size.height;rpx = screenWidth / standardWidth;px = screenWidth / standardWidth * 2;
}
// 按照像素來設(shè)置
static double setPx(double size) {
return Adapt.rpx * size * 2;
}
// 按照rxp來設(shè)置
static double setRpx(double size) {
return Adapt.rpx * size;
}
}
示例代碼
和上面的需求是一樣的,最后適配的效果是一樣的
@override
Widget build(BuildContext context) {
Adapt.initialize(context);
returnScaffold(
appBar: AppBar(
title: const Text('屏幕適配'),
),
body: Center(
child: Container(
width: Adapt.setPx(300),
height: Adapt.setPx(300),
color: Colors.orange,
alignment: Alignment.center,
child: Text(
'Hello Word',
style: TextStyle(fontSize: Adapt.setPx(30)),
textAlign: TextAlign.center,
),
),
),
);
}

注意:一定要在已經(jīng)有 MaterialApp 的 Widget 中使用 context ,否則是無效的。我這里定義默認(rèn)效果圖的尺寸是 375*667,這里是可以自定義傳入效果圖的寬度的。
3. flutter_screenutil 插件
pubspec.yaml中引入
flutter_screenutil: ^5.0.1
在已經(jīng)有 MaterialApp 的 Widget 中使用 context 進(jìn)行初始化文章來源:http://www.zghlxwxcb.cn/news/detail-462243.html
ScreenUtil.init(context,width:750,height:1334,allowFontScaling:false);
示例代碼
Container(
width: ScreenUtil().setWidth(300),
height: ScreenUtil().setHeight(300)
}
Text(
'Hello Word',
style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(30)),
textAlign: TextAlign.center,
)
其他更多用法可以參考官網(wǎng)文檔:pub.flutter-io.cn/packages/fl…文章來源地址http://www.zghlxwxcb.cn/news/detail-462243.html
到了這里,關(guān)于Flutter屏幕適配的三種方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!