[譯] Flutter —— 根據不同螢幕尺寸高效的適配 UI

小德_REN發表於2019-06-28

[譯] Flutter —— 根據不同螢幕尺寸高效的適配 UI

Flutter 是什麼?

如果你對這篇文章感興趣的話,說明你已經對 Flutter 有了一定的瞭解,閱讀本篇文章你需要記住的最重要的內容就是,Flutter 是可以控制螢幕上的任何一個畫素的(因為在 Native 開發裡是不能控制狀態列裡的畫素的,但 Flutter 可以控制狀態列,所以是可以控制螢幕上的任何一個畫素)。

本篇文章的核心

因為可以控制所有的畫素,如果我們想畫一個矩形,就可以這樣實現:

Container(
 height: 40,
 width: 60,
),
複製程式碼

現在,我們就用 Container 實現了一個 40 * 60 的矩形,接下來看一下這個矩形在 iPhone 5s (4" Display) 和 iPhone XS Max (6,46" Display) 顯示的樣子:

[譯] Flutter —— 根據不同螢幕尺寸高效的適配 UI

如上圖,你已經注意到,矩形在 iPhone Xs Max 上比 iPhone 5s 要小。

這是因為 Flutter 不管你的 App 是執行在 iPhone 5s,iPhone Xs Max 或者 13 存的 iPad 上,矩形的大小一直都是 40 x 60。

那麼如何解決呢?

首先,為了便於理解,我們先用檢視的方式來說明如何解決這個問題,當弄明白了之後,在去寫程式碼。

首先,拿出一個空的 view,然後給他加上網格,如下圖:

[譯] Flutter —— 根據不同螢幕尺寸高效的適配 UI

然後,我們把網格的單元成為 'Blocks'。

最終,我們使用 'Blocks' 來劃分矩形的寬和高,然後使用 'Blocks' 來代表 view 的大小,假設將寬高都分成 100 分,這樣我們就可以在每個顯示尺寸上擁有一致的 UI。

編碼實現

建立一個新的 Dart 檔案 size_config.dart,在這個檔案裡定義一個 SizeConfig 的類。

import ‘package:flutter/widgets.dart’;
 
class SizeConfig {}
複製程式碼

為了使用 Flutter 裡的 MediaQueryData 類,MediaQueryData 裡包含當前裝置的螢幕尺寸資訊,我們需要引入 widgets.dart。

然後在 SizeConfig 裡定義如下的屬性:

import ‘package:flutter/widgets.dart’;
class SizeConfig {
 static MediaQueryData _mediaQueryData;
 static double screenWidth;
 static double screenHeight;
 static double blockSizeHorizontal;
 static double blockSizeVertical;
}
複製程式碼

我們需要寫一個建構函式去初始化這些屬性:

class SizeConfig {
 static MediaQueryData _mediaQueryData;
 static double screenWidth;
 static double screenHeight;
 static double blockSizeHorizontal;
 static double blockSizeVertical;
 
 void init(BuildContext context) {
  _mediaQueryData = MediaQuery.of(context);
  screenWidth = _mediaQueryData.size.width;
  screenHeight = _mediaQueryData.size.height;
  blockSizeHorizontal = screenWidth / 100;
  blockSizeVertical = screenHeight / 100;
 }
}
複製程式碼

然後就是要在你的 home screen 裡初始化 SizeConfig。

class HomeScreen extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 SizeConfig().init(context);
 …
 }
}
複製程式碼

然後我們就可以使用 SizeConfig 裡的屬性去定義你的 Container 的寬高。

Widget build(BuildContext context) {
 return Center(
  child: Container(
   height: SizeConfig.blockSizeVertical * 20,
   width: SizeConfig.blockSizeHorizontal * 50,
   color: Colors.orange,
  ),
 );
}
複製程式碼

最後,在不同的螢幕上,矩形的寬都是螢幕寬的 50%,矩形的高都是螢幕高的 20%。

下面就是矩形顯示在 iPhone 5s 和 iPhone XS Max 的樣子。

[譯] Flutter —— 根據不同螢幕尺寸高效的適配 UI

擴充套件

如果你在 Flutter 開發上已經有了很多經驗,你可能已經處理過劉海屏、狀態列、導航欄這些東西。

在 Flutter 中有一個很方便的處理這些東西的 Widget,叫 'SafeArea'。

如何在我們網格的方法中實現 SafeArea 的功能

我們需要在 SizeConfig 里加入一些其他屬性去計算 SafeArea 應占的空間,並從網格中去除它。

class SizeConfig {
 static MediaQueryData _mediaQueryData;
 static double screenWidth;
 static double screenHeight;
 static double blockSizeHorizontal;
 static double blockSizeVertical;
 
 static double _safeAreaHorizontal;
 static double _safeAreaVertical;
 static double safeBlockHorizontal;
 static double safeBlockVertical;
 
 void init(BuildContext context) {
 _mediaQueryData = MediaQuery.of(context);
 screenWidth = _mediaQueryData.size.width;
 screenHeight = _mediaQueryData.size.height;
 blockSizeHorizontal = screenWidth / 100;
 blockSizeVertical = screenHeight / 100;
 
 _safeAreaHorizontal = _mediaQueryData.padding.left + 
 _mediaQueryData.padding.right;
 _safeAreaVertical = _mediaQueryData.padding.top +
 _mediaQueryData.padding.bottom;
 safeBlockHorizontal = (screenWidth -
 _safeAreaHorizontal) / 100;
 safeBlockVertical = (screenHeight -
 _safeAreaVertical) / 100;
 }
}
複製程式碼

這樣就可以讓你高效的適配 UI 而不用擔心 SafaArea。

如何適配文字?

你可以使用同樣的網格方法去適配文字,我通常使用 SizeConfig.safeBlockHorizontal 來適配文字,但是你可以使用 SizeConfig.blockSizeVertical 來適配。

適配後的效果如下:

[譯] Flutter —— 根據不同螢幕尺寸高效的適配 UI

本篇文章程式碼的 GitHub

本篇文章裡所有用到的程式碼,都可以在下面的 GitHub 裡找到:

github.com/dancamdev/e…

原文

medium.com/flutter-com…

相關文章