轉(zhuǎn)載
https://blog.csdn.net/u011272795/article/details/82795477
前言:
現(xiàn)在的手機(jī)品牌和型號越來越多,導(dǎo)致我們平時寫布局的時候會在個不同的移動設(shè)備上顯示的效果不同黄娘,
比如我們的設(shè)計(jì)稿一個View的大小是300px糯而,如果直接寫300px天通,可能在當(dāng)前設(shè)備顯示正常,但到了其他設(shè)備可能就會偏小或者偏大熄驼,這就需要我們對屏幕進(jìn)行適配像寒。
安卓原生的話有自己的適配規(guī)則,可以根據(jù)不同的尺寸建立不同的文件夾瓜贾,系統(tǒng)會根據(jù)當(dāng)前的設(shè)備尺寸取對應(yīng)的大小的布局诺祸。而flutter本身并沒有適配規(guī)則,而原生的又比較繁瑣祭芦,這就需要我們自己去對屏幕進(jìn)行適配筷笨。
點(diǎn)擊直達(dá)github地址
如果有幫助,請給我個star
flutter_ScreenUtil
flutter 屏幕適配方案
github: https://github.com/OpenFlutter/flutter_ScreenUtil
csdn博客工具介紹:https://blog.csdn.net/u011272795/article/details/82795477
使用方法:
安裝依賴:
安裝之前請查看最新版本
dependencies:
flutter:
sdk: flutter
# 添加依賴
flutter_screenutil: ^0.4.2
在每個使用的地方導(dǎo)入包:
import 'package:flutter_screenutil/flutter_screenutil.dart';
1
初始化設(shè)置尺寸
在使用之前請?jiān)O(shè)置好設(shè)計(jì)稿的寬度和高度实束,傳入設(shè)計(jì)稿的寬度和高度(單位px)
一定在MaterialApp的home中的頁面設(shè)置(即入口文件奥秆,只需設(shè)置一次),以保證在每次使用之前設(shè)置好了適配尺寸:
//設(shè)置適配尺寸 (填入設(shè)計(jì)稿中設(shè)備的屏幕尺寸) 假如設(shè)計(jì)稿是按iPhone6的尺寸設(shè)計(jì)的(iPhone6 750*1334)
ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
1
2
使用:
適配尺寸:
傳入設(shè)計(jì)稿的px尺寸:
根據(jù)屏幕寬度適配 width: ScreenUtil().setWidth(540),
根據(jù)屏幕高度適配 height: ScreenUtil().setHeight(200),
注意
高度也根據(jù)setWidth來做適配可以保證不變形(當(dāng)你想要一個正方形的時候)
setHeight方法主要是在高度上進(jìn)行適配, 在你想控制UI上一屏的高度與實(shí)際中顯示一樣時使用.
例如:
//長方形:
Container(
width: ScreenUtil().setWidth(375),
height: ScreenUtil().setHeight(200),
),
//如果你想顯示一個正方形:
Container(
width: ScreenUtil().setWidth(300),
height: ScreenUtil().setWidth(300),
),
適配字體:
ScreenUtil().setSp(28) //傳入字體大小,根據(jù)系統(tǒng)的“字體大小”輔助選項(xiàng)來進(jìn)行縮放
ScreenUtil().setSp(28咸灿,false) //傳入字體大小构订,不會根據(jù)系統(tǒng)的“字體大小”輔助選項(xiàng)來進(jìn)行縮放
for example:
Text(
'My font size is 28px and will not change with the system.',
style: TextStyle(
color: Colors.black,
fontSize: ScreenUtil().setSp(28, false)
)
),
其他相關(guān)api:
ScreenUtil.pixelRatio //設(shè)備的像素密度
ScreenUtil.screenWidth //設(shè)備寬度
ScreenUtil.screenHeight //設(shè)備高度
ScreenUtil.bottomBarHeight //底部安全區(qū)距離,適用于全面屏下面有按鍵的
ScreenUtil.statusBarHeight //狀態(tài)欄高度 劉海屏?xí)? 單位px
ScreenUtil.textScaleFactory //系統(tǒng)字體縮放比例
ScreenUtil().scaleWidth // 實(shí)際寬度的dp與設(shè)計(jì)稿px的比例
ScreenUtil().scaleHeight // 實(shí)際高度的dp與設(shè)計(jì)稿px的比例
//導(dǎo)入
import 'package:flutter_screenutil/flutter_screenutil.dart';
@override
Widget build(BuildContext context) {
//設(shè)置適配尺寸 (填入設(shè)計(jì)稿中設(shè)備的屏幕尺寸) 假如設(shè)計(jì)稿是按iPhone6的尺寸設(shè)計(jì)的(iPhone6 750*1334)
ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
print('設(shè)備寬度:${ScreenUtil.screenWidth}'); //Device width
print('設(shè)備高度:${ScreenUtil.screenHeight}'); //Device height
print('設(shè)備的像素密度:${ScreenUtil.pixelRatio}'); //Device pixel density
print(
'底部安全區(qū)距離:${ScreenUtil.bottomBarHeight}'); //Bottom safe zone distance避矢,suitable for buttons with full screen
print(
'狀態(tài)欄高度:${ScreenUtil.statusBarHeight}px'); //Status bar height , Notch will be higher Unit px
print('實(shí)際寬度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleWidth}');
print('實(shí)際高度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleHeight}');
print(
'寬度和字體相對于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}');
print(
'高度相對于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}');
print('系統(tǒng)的字體縮放比例:${ScreenUtil.textScaleFactory}');
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
children: <Widget>[
Container(
width: ScreenUtil().setWidth(375),
height: ScreenUtil().setHeight(200),
color: Colors.red,
child: Text(
'我的寬度:${ScreenUtil().setWidth(375)}dp',
style: TextStyle(
color: Colors.white,
fontSize: ScreenUtil().setSp(12, false),
),
),
),
Container(
width: ScreenUtil().setWidth(375),
height: ScreenUtil().setHeight(200),
color: Colors.blue,
child: Text('我的寬度:${ScreenUtil().setWidth(375)}dp',
style: TextStyle(
color: Colors.white,
fontSize: ScreenUtil().setSp(12, false),
)),
),
],
),
Text('設(shè)備寬度:${ScreenUtil.screenWidth}px'),
Text('設(shè)備高度:${ScreenUtil.screenHeight}px'),
Text('設(shè)備的像素密度:${ScreenUtil.pixelRatio}'),
Text('底部安全區(qū)距離:${ScreenUtil.bottomBarHeight}px'),
Text('狀態(tài)欄高度:${ScreenUtil.statusBarHeight}px'),
Text(
'實(shí)際高度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleHeight}',
textAlign: TextAlign.center,
),
Text(
'實(shí)際高度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleHeight}',
textAlign: TextAlign.center,
),
Text(
'寬度和字體相對于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}',
textAlign: TextAlign.center,
),
Text(
'高度相對于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}',
textAlign: TextAlign.center,
),
SizedBox(
height: ScreenUtil().setHeight(100),
),
Text('系統(tǒng)的字體縮放比例:${ScreenUtil.textScaleFactory}'),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('我的文字大小在設(shè)計(jì)稿上是14px悼瘾,不會隨著系統(tǒng)的文字縮放比例變化',
style: TextStyle(
color: Colors.black,
fontSize: ScreenUtil().setSp(14, false))),
Text('我的文字大小在設(shè)計(jì)稿上是14px囊榜,會隨著系統(tǒng)的文字縮放比例變化',
style: TextStyle(
color: Colors.black, fontSize: ScreenUtil().setSp(14))),
],
)
],
),
),
);
}
使用示例:
example demo
說一下適配方案, 比如我們設(shè)計(jì)師設(shè)計(jì)的UI是根據(jù)Iphone6來做的,我們知道 iPhone6的分辨率是750*1334(px),
又或者是根據(jù)hdpi的設(shè)備來設(shè)計(jì)的UI,我們知道hdpi的 Android設(shè)備是 (240 dpi),像素密度是1.5,即hdpi設(shè)備的分辨率寬度是320px, 總之,無論設(shè)計(jì)稿的單位是px,或者是dp,我們都能夠轉(zhuǎn)換成px.
那么我們?nèi)绻鶕?jù)px來適配,ios和 android 就都可以兼容了.
假設(shè),我們的設(shè)計(jì)稿手機(jī)是10801920 px.
設(shè)計(jì)稿上有一個540960 的組件, 即寬度和寬度是手機(jī)的一半. 如果我們直接寫的時候組件的尺寸這么定義,在其他尺寸的設(shè)備上未必是一半,或多,或少. 但是我們可以按比例來看,即我們要實(shí)現(xiàn)的寬度是實(shí)際設(shè)備的一半.
那么假設(shè)我們設(shè)備的寬度是deviceWidth和deviceHeight , 我們要寫的組件大小為: 寬:(540/1080)deviceWidth,高度: (960/1920)deviceHeight.
通過這個公式我們可以發(fā)現(xiàn),我們要寫的組件寬度就是設(shè)計(jì)稿上的尺寸width(deviceWdith/原型設(shè)備寬度).那么每次我們寫ui的時候,只要直接哪來設(shè)計(jì)稿的尺寸(deviceWdith/設(shè)備原型)寬度即可.
原理就是先獲取,實(shí)際設(shè)備與原型設(shè)備的尺寸比例.
首先flutter獲取設(shè)備的尺寸的代碼是:
以下數(shù)據(jù)為我的手機(jī)數(shù)據(jù):
import 'dart:ui';
//因?yàn)閣indow是dart:ui中提供的,所以需要引入這個包.
window.physicalSize //Size(1080.0, 1794.0) 單位px
width = window.physicalSize.width //寬度
height = window.physicalSize.height //高度
//使用這個方法則無需引入包
MediaQuery.of(context).size //Size(411.4, 683.4) 單位:dp
widhtDp = MediaQuery.of(context).size.width //寬度 411.4
heightDp = MediaQuery.of(context).size.height //高度 683.4
設(shè)計(jì)稿單位是px,且尺寸為1080*1920 px 時:
scaleWidth = width / 1080;
scaleHeight = height / 1920;
那么我們要寫尺寸為500100控件的寬度就是 500scaleWidth .100*scaleHeigh ,注意這時單位是px,flutter中默認(rèn)組件尺寸單位都是dp,我們還要進(jìn)行px->dp的操作.除以像素密度就好了.
flutter獲取像素密度的方法:
MediaQuery.of(context).devicePixelRatio
window.physicalSize
上面兩種方法得到的是一樣的結(jié)果,但是window對象來自dart:ui,所以我們引入這個包:
import ‘dart:ui’;
設(shè)計(jì)稿單位是dp,且尺寸為360*640 dp 時:
scaleWidth = widhtDp / 360;
scaleHeight = heightDp / 640;
那么我們要寫尺寸為500100控件的寬度就是 500scaleWidth .100*scaleHeigh