目前移動端的設備已經非常多,並且不同的設備手機屏幕也不相同。
目前做移動端開發都要針對不同的設備進行一定的適配,無論是移動原生開發、小程序、H5頁面。
Flutter中如何針對不同的手機屏幕來進行適配呢?我們一起來聊聊這個話題。
一. Flutter單位
1.1. Flutter中的單位
在進行Flutter開發時,我們通常不需要傳入尺寸的單位,那麼Flutter使用的是什麼單位呢?
- Flutter使用的是類似於iOS中的點pt,也就是point。
- 所以我們經常說iPhone6的尺寸是375x667,但是它的分辨率其實是750x1334。
- 因為iPhone6的dpr(devicePixelRatio)是2.0,iPhone6plus的dpr是3.0
在Flutter開發中,我們使用的是對應的邏輯分辨率
1.2. Flutter設備信息
獲取屏幕上的一些信息,可以通過MediaQuery:
<code>final
mediaQueryData = MediaQuery.of(context);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
");final
statusBarHeight = mediaQueryData.padding.top;final
bottomHeight = mediaQueryData.padding.bottom; print("狀態欄height:
$statusBarHeight
底部高度:$bottomHeight
");/<code>
獲取一些設備相關的信息,可以使用官方提供的一個庫:
<code>dependencies
:device_info
: ^0.4
.2
+1/<code>
二. 適配方案
2.1. 適配概述
假如我們有下面這樣一段代碼:
- 在屏幕中間顯示一個200*200的Container
- Container中有一段文字是30
<code>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),), ), ), ); } }/<code>
上面的代碼在不同屏幕上會有不同的表現:
- 很明顯,如果按照上面的規則,在iPhone5上面,尺寸過大,在iPhone6plus上面尺寸過小
- 在開發中,我們應該可以根據不同的屏幕來完成尺寸的縮放
在前端開發中,針對不同的屏幕常見的適配方案有下面幾種:
- rem:
- rem是給根標籤(HTML標籤)設置一個字體大小;
- 但是不同的屏幕要動畫設置不同的字體大小(可以通過媒體查詢,也可以通過js動態計算);
- 其它所有的單位都使用rem單位(相對於根標籤);
- vw、wh:
- vw和vh是將屏幕(視口)分成100等份,一個1vw相當於是1%的大小;
- 其它所有的單位都使用vw或wh單位;
- rpx:
- rpx是小程序中的適配方案,它將750px作為設計稿,1rpx=屏幕寬度/750;
- 其它所有的單位都使用rpx單位;
這裡我採用小程序的rpx來完成Flutter的適配
2.2. rpx適配
小程序中rpx的原理是什麼呢?
- 不管是什麼屏幕,統一分成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,利用媒體查詢獲取屏幕的寬度和高度
- 也可以傳入一個可選的參數,以什麼尺寸作為設計稿
<code>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
; }static
double
setRpx
(
double
size) {return
HYSizeFit.rpx * size; } }/<code>
初始化HYSizeFit類的屬性:
- 注意:必須在已經有MaterialApp的Widget中使用context,否則是無效的
<code>class
HYHomePage
extends
StatelessWidget
{Widget
build
(BuildContext context)
{ HYSizeFit.initialize(context);return
null
; } }/<code>
使用rpx來完成屏幕適配:
<code>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),), ), ), ); } }/<code>
我們來看一下實現效果:
屏幕適配也可以使用第三方庫:flutter_screenutil
- https://github.com/OpenFlutter/flutter_screenutil
原文出處:https://mp.weixin.qq.com/s/z21YZ4FhSswpDWn4KpK6jw(侵權刪除)
關鍵字: mediaQueryData HYSizeFit Flutter