如今的手機品牌和型號愈來愈多,致使咱們平時寫佈局的時候會在個不一樣的移動設備上顯示的效果不一樣,android
好比咱們的設計稿一個View的大小是300px,若是直接寫300px,可能在當前設備顯示正常,但到了其餘設備可能就會偏小或者偏大,這就須要咱們對屏幕進行適配。ios
安卓原生的話有本身的適配規則,能夠根據不一樣的尺寸創建不一樣的文件夾,系統會根據當前的設備尺寸取對應的大小的佈局。而flutter自己並無適配規則,而原生的又比較繁瑣,這就須要咱們本身去對屏幕進行適配。git
點擊直達github地址github
若是有幫助,請給我個star
最新代碼請訪問githubapi
flutter 屏幕適配方案安全
github: github.com/OpenFlutter…
csdn博客工具介紹:blog.csdn.net/u011272795/…bash
安裝以前請查看最新版本markdown
dependencies: flutter: sdk: flutter # 添加依賴 flutter_screenutil: ^0.4.0 複製代碼
import 'package:flutter_screenutil/flutter_screenutil.dart'; 複製代碼
在使用以前請設置好設計稿的寬度和高度,傳入設計稿的寬度和高度(單位px) 必定在MaterialApp的home中的頁面設置,以保證在每次使用以前設置好了適配尺寸:app
//設置適配尺寸 (填入設計稿中設備的屏幕尺寸) 假如設計稿是按iPhone6的尺寸設計的(iPhone6 750*1334)
ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
複製代碼
適配尺寸:ide
//傳入設計稿的px尺寸: 適配後的寬度width: ScreenUtil().setWidth(540), 適配後的高度height: ScreenUtil().setHeight(200), 高度也根據setWidth來作適配能夠保證不變形 例如: Container( width: ScreenUtil().setWidth(375), height: ScreenUtil().setHeight(200), ), 複製代碼
適配字體:
ScreenUtil().setSp(28) //傳入字體大小,根據系統的「字體大小」輔助選項來進行縮放 ScreenUtil().setSp(28,false) //傳入字體大小,不會根據系統的「字體大小」輔助選項來進行縮放 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) ) ), 複製代碼
其餘相關api:
ScreenUtil.pixelRatio //設備的像素密度
ScreenUtil.screenWidth //設備寬度
ScreenUtil.screenHeight //設備高度
ScreenUtil.bottomBarHeight //底部安全區距離,適用於全面屏下面有按鍵的
ScreenUtil.statusBarHeight //狀態欄高度 劉海屏會更高 單位px
ScreenUtil.textScaleFactory //系統字體縮放比例
ScreenUtil().scaleWidth // 實際寬度的dp與設計稿px的比例
ScreenUtil().scaleHeight // 實際高度的dp與設計稿px的比例
複製代碼
//導入 import 'package:flutter_screenutil/flutter_screenutil.dart'; ... @override Widget build(BuildContext context) { //設置適配尺寸 (填入設計稿中設備的屏幕尺寸) 假如設計稿是按iPhone6的尺寸設計的(iPhone6 750*1334) ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context); print('設備寬度:${ScreenUtil.screenWidth}'); //Device width print('設備高度:${ScreenUtil.screenHeight}'); //Device height print('設備的像素密度:${ScreenUtil.pixelRatio}'); //Device pixel density print( '底部安全區距離:${ScreenUtil.bottomBarHeight}'); //Bottom safe zone distance,suitable for buttons with full screen print( '狀態欄高度:${ScreenUtil.statusBarHeight}px'); //Status bar height , Notch will be higher Unit px print('實際寬度的dp與設計稿px的比例:${ScreenUtil().scaleWidth}'); print('實際高度的dp與設計稿px的比例:${ScreenUtil().scaleHeight}'); print( '寬度和字體相對於設計稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}'); print( '高度相對於設計稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}'); print('系統的字體縮放比例:${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('設備寬度:${ScreenUtil.screenWidth}px'), Text('設備高度:${ScreenUtil.screenHeight}px'), Text('設備的像素密度:${ScreenUtil.pixelRatio}'), Text('底部安全區距離:${ScreenUtil.bottomBarHeight}px'), Text('狀態欄高度:${ScreenUtil.statusBarHeight}px'), Text( '實際高度的dp與設計稿px的比例:${ScreenUtil().scaleHeight}', textAlign: TextAlign.center, ), Text( '實際高度的dp與設計稿px的比例:${ScreenUtil().scaleHeight}', textAlign: TextAlign.center, ), Text( '寬度和字體相對於設計稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}', textAlign: TextAlign.center, ), Text( '高度相對於設計稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}', textAlign: TextAlign.center, ), SizedBox( height: ScreenUtil().setHeight(100), ), Text('系統的字體縮放比例:${ScreenUtil.textScaleFactory}'), Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text('個人文字大小在設計稿上是14px,不會隨着系統的文字縮放比例變化', style: TextStyle( color: Colors.black, fontSize: ScreenUtil().setSp(14, false))), Text('個人文字大小在設計稿上是14px,會隨着系統的文字縮放比例變化', style: TextStyle( color: Colors.black, fontSize: ScreenUtil().setSp(14))), ], ) ], ), ), ); } 複製代碼
效果:
說一下適配方案, 好比咱們設計師設計的UI是根據Iphone6來作的,咱們知道 iPhone6的分辨率是750*1334(px), 又或者是根據hdpi的設備來設計的UI,咱們知道hdpi的 Android設備是 (240 dpi),像素密度是1.5,即hdpi設備的分辨率寬度是320px, 總之,不管設計稿的單位是px,或者是dp,咱們都可以轉換成px. 那麼咱們若是根據px來適配,ios和 android 就均可以兼容了.
假設,咱們的設計稿手機是10801920 px. 設計稿上有一個540960 的組件, 即寬度和寬度是手機的一半. 若是咱們直接寫的時候組件的尺寸這麼定義,在其餘尺寸的設備上未必是一半,或多,或少. 可是咱們能夠按比例來看,即咱們要實現的寬度是實際設備的一半. 那麼假設咱們設備的寬度是deviceWidth和deviceHeight , 咱們要寫的組件大小爲: 寬:(540/1080)*deviceWidth,高度: (960/1920)*deviceHeight.
經過這個公式咱們能夠發現,咱們要寫的組件寬度就是設計稿上的尺寸width*(deviceWdith/原型設備寬度).那麼每次咱們寫ui的時候,只要直接哪來設計稿的尺寸*(deviceWdith/設備原型)寬度便可.
原理就是先獲取,實際設備與原型設備的尺寸比例. 首先flutter獲取設備的尺寸的代碼是:
如下數據爲個人手機數據: import 'dart:ui'; //由於window是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 複製代碼
設計稿單位是px,且尺寸爲1080*1920 px 時:
scaleWidth = width / 1080;
scaleHeight = height / 1920;
複製代碼
那麼咱們要寫尺寸爲500100控件的寬度就是 500scaleWidth .100*scaleHeigh ,注意這時單位是px,flutter中默認組件尺寸單位都是dp,咱們還要進行px->dp的操做.除以像素密度就行了. flutter獲取像素密度的方法:
MediaQuery.of(context).devicePixelRatio
window.physicalSize
複製代碼
上面兩種方法獲得的是同樣的結果,可是window對象來自dart:ui,因此咱們引入這個包:
import 'dart:ui';
設計稿單位是dp,且尺寸爲360*640 dp 時:
scaleWidth = widhtDp / 360;
scaleHeight = heightDp / 640;
那麼咱們要寫尺寸爲500*100控件的寬度就是 500*scaleWidth .100*scaleHeigh
複製代碼
setSp(int fontSize, [allowFontScaling = true]) => allowFontScaling ? setWidth(fontSize) * _textScaleFactor : setWidth(fontSize); 複製代碼
第一個參數爲設計稿中字體的大小,單位px, 第二個參數可選,爲控制字體是否要根據系統的「字體大小」輔助選項來進行縮放。默認值爲true。