Flutter(十九)屏幕適配

目前移動端的設備已經非常多伍伤,并且不同的設備手機屏幕也不相同。

目前做移動端開發(fā)都要針對不同的設備進行一定的適配遣钳,無論是移動原生開發(fā)扰魂、小程序、H5頁面蕴茴。

Flutter中如何針對不同的手機屏幕來進行適配呢劝评?我們一起來聊聊這個話題。

一. Flutter單位

1.1. Flutter中的單位

在進行Flutter開發(fā)時倦淀,我們通常不需要傳入尺寸的單位蒋畜,那么Flutter使用的是什么單位呢?

  • Flutter使用的是類似于iOS中的點pt撞叽,也就是point百侧。
  • 所以我們經常說iPhone6的尺寸是375x667,但是它的分辨率其實是750x1334能扒。
  • 因為iPhone6的dpr(devicePixelRatio)是2.0佣渴,iPhone6plus的dpr是3.0
圖片

在Flutter開發(fā)中,我們使用的是對應的邏輯分辨率

1.2. Flutter設備信息

獲取屏幕上的一些信息初斑,可以通過MediaQuery:

// 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;
print("屏幕width:$screenWidth height:$screenHeight");
print("分辨率: $physicalWidth - $physicalHeight");
print("dpr: $dpr");

// 3.狀態(tài)欄的高度
// 有劉海的屏幕:44 沒有劉海的屏幕為20
final statusBarHeight = mediaQueryData.padding.top;
// 有劉海的屏幕:34 沒有劉海的屏幕0
final bottomHeight = mediaQueryData.padding.bottom;
print("狀態(tài)欄height: $statusBarHeight 底部高度:$bottomHeight");

獲取一些設備相關的信息辛润,可以使用官方提供的一個庫:

dependencies:
  device_info: ^0.4.2+1

二. 適配方案

2.1. 適配概述

假如我們有下面這樣一段代碼:

  • 在屏幕中間顯示一個200*200的Container
  • Container中有一段文字是30
class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("首頁"),
      ),
      body: Center(
        child: Container(
          width: 200,
          height: 200,
          color: Colors.red,
          alignment: Alignment.center,
          child: Text("Hello World", style: TextStyle(fontSize: 30, color: Colors.white),),
        ),
      ),
    );
  }
}

上面的代碼在不同屏幕上會有不同的表現(xiàn):

  • 很明顯,如果按照上面的規(guī)則见秤,在iPhone5上面砂竖,尺寸過大,在iPhone6plus上面尺寸過小

  • 在開發(fā)中鹃答,我們應該可以根據不同的屏幕來完成尺寸的縮放

圖片

在前端開發(fā)中乎澄,針對不同的屏幕常見的適配方案有下面幾種:

  • rem:

  • rem是給根標簽(HTML標簽)設置一個字體大小测摔;

  • 但是不同的屏幕要動畫設置不同的字體大兄眉谩(可以通過媒體查詢解恰,也可以通過js動態(tài)計算);

  • 其它所有的單位都使用rem單位(相對于根標簽)浙于;

  • vw护盈、wh:

  • vw和vh是將屏幕(視口)分成100等份,一個1vw相當于是1%的大行咝铩腐宋;

  • 其它所有的單位都使用vw或wh單位;

  • rpx:

  • rpx是小程序中的適配方案檀轨,它將750px作為設計稿胸竞,1rpx=屏幕寬度/750;

  • 其它所有的單位都使用rpx單位参萄;

這里我采用小程序的rpx來完成Flutter的適配

2.2. rpx適配

小程序中rpx的原理是什么呢撤师?

  • 不管是什么屏幕,統(tǒng)一分成750份
  • 在iPhone5上:1rpx = 320/750 = 0.4266 ≈ 0.42px
  • 在iPhone6上:1rpx = 375/750 = 0.5px
  • 在iPhone6plus上:1rpx = 414/750 = 0.552px
圖片

那么我們就可以通過上面的計算方式拧揽,算出一個rpx剃盾,再將自己的size和rpx單位相乘即可:

  • 比如100px的寬度:100 * 2 * rpx
  • 在iPhone5上計算出的結果是84px
  • 在iPhone6上計算出的結果是100px
  • 在iPhone6plus上計算出的結果是110.4px

我們自己來封裝一個工具類:

  • 工具類需要進行初始化,傳入context

  • 可以通過傳入context淤袜,利用媒體查詢獲取屏幕的寬度和高度

  • 也可以傳入一個可選的參數(shù)痒谴,以什么尺寸作為設計稿

class HYSizeFit {
  static MediaQueryData _mediaQueryData;
  static double screenWidth;
  static double screenHeight;
  static double rpx;
  static double px;

  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;
  }
  
  // 按照像素來設置
  static double setPx(double size) {
    return HYSizeFit.rpx * size * 2;
  }
  
  // 按照rxp來設置
  static double setRpx(double size) {
    return HYSizeFit.rpx * size;
  }
}

初始化HYSizeFit類的屬性:

  • 注意:必須在已經有MaterialApp的Widget中使用context,否則是無效的
class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 初始化HYSizeFit
    HYSizeFit.initialize(context);
    return null;
  }
}

使用rpx來完成屏幕適配:

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    HYSizeFit.initialize(context);
    return Scaffold(
      appBar: AppBar(
        title: Text("首頁"),
      ),
      body: Center(
        child: Container(
          width: HYSizeFit.setPx(200),
          height: HYSizeFit.setRpx(400),
          color: Colors.red,
          alignment: Alignment.center,
          child: Text("Hello World", style: TextStyle(fontSize: HYSizeFit.setPx(30), color: Colors.white),),
        ),
      ),
    );
  }
}

我們來看一下實現(xiàn)效果:

圖片

屏幕適配也可以使用第三方庫:flutter_screenutil

參考:小碼哥Flutter

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末铡羡,一起剝皮案震驚了整個濱河市积蔚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌烦周,老刑警劉巖尽爆,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異读慎,居然都是意外死亡漱贱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門夭委,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幅狮,“玉大人,你說我怎么就攤上這事株灸〕缟悖” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵慌烧,是天一觀的道長逐抑。 經常有香客問我,道長屹蚊,這世上最難降的妖魔是什么厕氨? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任进每,我火速辦了婚禮,結果婚禮上腐巢,老公的妹妹穿的比我還像新娘。我一直安慰自己玄括,他們只是感情好冯丙,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著遭京,像睡著了一般胃惜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哪雕,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天船殉,我揣著相機與錄音,去河邊找鬼斯嚎。 笑死利虫,一個胖子當著我的面吹牛,可吹牛的內容都是我干的堡僻。 我是一名探鬼主播糠惫,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钉疫!你這毒婦竟也來了硼讽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤牲阁,失蹤者是張志新(化名)和其女友劉穎固阁,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體城菊,經...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡备燃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凌唬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赚爵。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖法瑟,靈堂內的尸體忽然破棺而出冀膝,到底是詐尸還是另有隱情,我是刑警寧澤霎挟,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布窝剖,位于F島的核電站,受9級特大地震影響酥夭,放射性物質發(fā)生泄漏赐纱。R本人自食惡果不足惜脊奋,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疙描。 院中可真熱鬧诚隙,春花似錦、人聲如沸起胰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽效五。三九已至地消,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間畏妖,已是汗流浹背脉执。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留戒劫,地道東北人半夷。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像迅细,于是被迫代替她去往敵國和親玻熙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內容