flutter UI的適配

轉(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亥宿,隨后出現(xiàn)的幾起案子卸勺,更是在濱河造成了極大的恐慌,老刑警劉巖烫扼,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曙求,死亡現(xiàn)場離奇詭異,居然都是意外死亡映企,警方通過查閱死者的電腦和手機(jī)悟狱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堰氓,“玉大人挤渐,你說我怎么就攤上這事∷酰” “怎么了浴麻?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長囤攀。 經(jīng)常有香客問我软免,道長,這世上最難降的妖魔是什么抚岗? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任或杠,我火速辦了婚禮,結(jié)果婚禮上宣蔚,老公的妹妹穿的比我還像新娘向抢。我一直安慰自己,他們只是感情好胚委,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布挟鸠。 她就那樣靜靜地躺著,像睡著了一般亩冬。 火紅的嫁衣襯著肌膚如雪艘希。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天硅急,我揣著相機(jī)與錄音覆享,去河邊找鬼。 笑死营袜,一個胖子當(dāng)著我的面吹牛撒顿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荚板,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼凤壁,長吁一口氣:“原來是場噩夢啊……” “哼吩屹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拧抖,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤煤搜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后唧席,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擦盾,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年袱吆,在試婚紗的時候發(fā)現(xiàn)自己被綠了厌衙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片距淫。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡绞绒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榕暇,到底是詐尸還是另有隱情蓬衡,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布彤枢,位于F島的核電站狰晚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缴啡。R本人自食惡果不足惜壁晒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望业栅。 院中可真熱鬧秒咐,春花似錦、人聲如沸碘裕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帮孔。三九已至雷滋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間文兢,已是汗流浹背晤斩。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姆坚,地道東北人澳泵。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像旷偿,于是被迫代替她去往敵國和親烹俗。 傳聞我的和親對象是個殘疾皇子爆侣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容