上圖
webUI
androidUI
不是dp適配
對的,不是對dp的適配,而是在不同的分變率,改變布局的方式。大的屏幕肯定是要合理利用空間,這樣布局緊湊,不浪費空間,小的屏幕又不能讓大的組件等比壓縮,這樣不光會變丑,還會變的更難觸及,既然Flutter對web的支持,那么肯定要支持不同分辨率,適配不同布局吧,就像我們Android開發,在針對Pad的時候做一個單獨的xml布局來適配一樣。
實現原理
原理很簡單,就是在屏幕寬度到了一定范圍內,然后動態返回不同的Widget,那么拿到屏幕的寬度就是關鍵,其實很簡單
MediaQuery.of(context).size.width
詳細介紹參見官方文檔MediaQuery
大致意思是說,WidgetsApp和MaterialApp目前只有它們引入了MediaQuery并隨著它們的變化與當前屏幕指標保持最新,所以這也是為什么當你沒有用這兩個widget布局,最終報錯的原因,用的時候注意。
我們來看個細節哈
WidgetsApp
MaterialApp
WidgetsApp和MaterialApp
繼承自StatefulWidget,我們平時寫的組件也大部分都是繼承自StatefulWidget,所以這就說明,你平時自己寫的組件,如果是一個單獨的新頁面,當你用到這個MediaQuery時肯定會報錯,不信你試試哈。
我們知道寬度后就好說了,只需要加入寬度判斷就ok
static bool isSmallScreen(BuildContext context) {
return MediaQuery.of(context).size.width < 768;
}
static bool isLargeScreen(BuildContext context) {
return MediaQuery.of(context).size.width > 768;
}
static bool isMediumScreen(BuildContext context) {
return MediaQuery.of(context).size.width > 425 &&
MediaQuery.of(context).size.width < 1200;
}
然后在Widget build(BuildContext context)的時候返回不同的布局
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 768) {
return largeScreen;
} else if (constraints.maxWidth < 1200 && constraints.maxWidth > 425) {
return mediumScreen ?? largeScreen;
} else {
return smallScreen ?? largeScreen;
}
},
);
如何使用呢
ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.maxWidth, minHeight: constraints.maxHeight),
child: ResponsiveWidget(
largeScreen: _buildLargeScreen(context),
mediumScreen: _buildMediumScreen(context),
smallScreen: _buildSmallScreen(context),
),
)
ConstrainedBox用于對子組件添加額外的約束,這里就是為了限制布局的寬高都充滿屏幕,準確的說是充滿父容器,保證計算的寬度不會出現失誤。
官方動態適配方案
官方解讀:
responsive響應式應用程序會根據屏幕或窗口的大小和形狀來布局其UI。當同一個應用程序可以在各種設備(從手表,手機,平板電腦到筆記本電腦或臺式機)上運行時,這尤其必要。當用戶在筆記本電腦或臺式機上調整窗口大小或更改手機或平板電腦的方向時,應用程序應通過相應地重新排列UI來做出響應。
官方推薦博客:
- Deven Joshi 在Flutter中開發多種屏幕尺寸和方向
- 在Flutter中構建響應式UI,作者Raouf Rahiche
- Priyanka Tyagi 使跨平臺的Flutter登陸頁面具有響應性
- 如何使Flutter應用根據不同的屏幕尺寸做出響應?,關于StackOverflow的問題
國外開源方案
image.png
responsive_builder這個框架的原理跟我介紹的一樣,封裝的會詳細一些。請參考。
我介紹的方案地址
在線看效果
結束
以后碰到Flutter中實用的東東,在分享給你們哈。歡迎留言討論。