Flutter組件適配方法實(shí)現(xiàn)詳解
Flutter 適配組件
在 Flutter 我們只需要掌握一些 Widget 即可,實(shí)際的開發(fā)過程中,我們也只需要在合適的地方使用它們即可。
1. MediaQuery
第一個(gè) Widget 即是 MediaQuery,通過它可以直接獲得屏幕的大?。▽挾?/ 高度)和方向(縱向 / 橫向)。
cclass HomePage extends StatelessWidget { @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; Orientation orientation = MediaQuery.of(context).orientation; return Scaffold( body: Container( color: CustomColors.android, child: Center( child: Text( 'View\n\n' + '[MediaQuery width]: ${screenSize.width.toStringAsFixed(2)}\n\n' + '[MediaQuery orientation]: $orientation', style: TextStyle(color: Colors.white, fontSize: 18), ), ), ), ); } }
2. LayoutBuilder
使用 LayoutBuilder 組件,可以獲得一個(gè) BoxConstraints 對(duì)象,通過該對(duì)象我們就可以拿到 Widget 的 maxWidth(最大寬度) 和maxHeight(最大高度)
MediaQuery 和 LayoutBuilder 的區(qū)別在在于,MediaQuery 得到的是整個(gè)屏幕的寬高,而 LayoutBuilder 得到的是特定組件的最大高度和寬度。
class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; return Scaffold( body: Row( children: [ Expanded( flex: 2, child: LayoutBuilder( builder: (context, constraints) => Container( color: CustomColors.android, child: Center( child: Text( 'View 1\n\n' + '[MediaQuery]:\n ${screenSize.width.toStringAsFixed(2)}\n\n' + '[LayoutBuilder]:\n${constraints.maxWidth.toStringAsFixed(2)}', style: TextStyle(color: Colors.white, fontSize: 18), ), ), ), ), ), Expanded( flex: 3, child: LayoutBuilder( builder: (context, constraints) => Container( color: Colors.white, child: Center( child: Text( 'View 2\n\n' + '[MediaQuery]:\n ${screenSize.width.toStringAsFixed(2)}\n\n' + '[LayoutBuilder]:\n${constraints.maxWidth.toStringAsFixed(2)}', style: TextStyle(color: CustomColors.android, fontSize: 18), ), ), ), ), ), ], ), ); } }
3. OrientationBuilder
要確定當(dāng)前 Widget 的方向,可以使用 OrientationBuilder 組件。這里的方向與 MediaQuery 提供的設(shè)備方向不同。
class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { Orientation deviceOrientation = MediaQuery.of(context).orientation; return Scaffold( body: Column( children: [ Expanded( flex: 2, child: Container( color: CustomColors.android, child: OrientationBuilder( builder: (context, orientation) => Center( child: Text( 'View 1\n\n' + '[MediaQuery orientation]:\n$deviceOrientation\n\n' + '[OrientationBuilder]:\n$orientation', style: TextStyle(color: Colors.white, fontSize: 18), ), ), ), ), ), Expanded( flex: 3, child: OrientationBuilder( builder: (context, orientation) => Container( color: Colors.white, child: Center( child: Text( 'View 2\n\n' + '[MediaQuery orientation]:\n$deviceOrientation\n\n' + '[OrientationBuilder]:\n$orientation', style: TextStyle(color: CustomColors.android, fontSize: 18), ), ), ), ), ), ], ), ); } }
4. Expanded 和 Flexible
Expanded 和 Flexible 這兩個(gè)組件可以和 Column/Row 搭配使用,來實(shí)現(xiàn)非常完美的自適應(yīng)效果。Expanded 可以用來拓展 Row, 、Column 和 Flex,從而讓子組件填充可用空間,F(xiàn)lexible 功能類似但并不一定能填充全部可用空間。
下面這個(gè)例子演示了混合使用 Expanded 和 Flexible 的各種方式:
class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: Column( children: [ Row( children: [ ExpandedWidget(), FlexibleWidget(), ], ), Row( children: [ ExpandedWidget(), ExpandedWidget(), ], ), Row( children: [ FlexibleWidget(), FlexibleWidget(), ], ), Row( children: [ FlexibleWidget(), ExpandedWidget(), ], ), ], ), ), ); } } class ExpandedWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Expanded( child: Container( decoration: BoxDecoration( color: CustomColors.android, border: Border.all(color: Colors.white), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Text( 'Expanded', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ), ); } } class FlexibleWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Flexible( child: Container( decoration: BoxDecoration( color: CustomColors.androidAccent, border: Border.all(color: Colors.white), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Text( 'Flexible', style: TextStyle(color: CustomColors.android, fontSize: 24), ), ), ), ); } }
5. FractionallySizedBox
FractionallySizedBox 組件可以使子組件填充部分可用空間,該特性在 Expanded 或 Flexible 中特別有用。
class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ FractionallySizedWidget(widthFactor: 0.4), ], ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ FractionallySizedWidget(widthFactor: 0.6), ], ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ FractionallySizedWidget(widthFactor: 0.8), ], ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ FractionallySizedWidget(widthFactor: 1.0), ], ), ], ), ), ); } } class FractionallySizedWidget extends StatelessWidget { final double widthFactor; FractionallySizedWidget({@required this.widthFactor}); @override Widget build(BuildContext context) { return Expanded( child: FractionallySizedBox( alignment: Alignment.centerLeft, widthFactor: widthFactor, child: Container( decoration: BoxDecoration( color: CustomColors.android, border: Border.all(color: Colors.white), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Text( '${widthFactor * 100}%', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ), ), ); } }
6. AspectRatio
AspectRatio 組件可以直接指定子組件的固定寬高比例,使用時(shí),我們可以使用布局約束的最大寬度,并給定一個(gè)寬高比自適應(yīng)其高度
class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: Column( children: [ AspectRatioWidget(ratio: '16 / 9'), AspectRatioWidget(ratio: '3 / 2'), ], ), ), ); } } class AspectRatioWidget extends StatelessWidget { final String ratio; AspectRatioWidget({@required this.ratio}); @override Widget build(BuildContext context) { return AspectRatio( aspectRatio: Fraction.fromString(ratio).toDouble(), child: Container( decoration: BoxDecoration( color: CustomColors.android, border: Border.all(color: Colors.white), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Center( child: Text( 'AspectRatio - $ratio', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ), ), ); } }
到此這篇關(guān)于Flutter組件適配方法實(shí)現(xiàn)詳解的文章就介紹到這了,更多相關(guān)Flutter組件適配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android?JetPack組件的支持庫Databinding詳解
DataBinding是Google發(fā)布的一個(gè)數(shù)據(jù)綁定框架,它能夠讓開發(fā)者減少重復(fù)性非常高的代碼,如findViewById這樣的操作。其核心優(yōu)勢是解決了數(shù)據(jù)分解映射到各個(gè)view的問題,在MVVM框架中,實(shí)現(xiàn)的View和Viewmode的雙向數(shù)據(jù)綁定2022-08-08Android 第三方應(yīng)用接入微信平臺(tái)研究情況分享(一)
微信平臺(tái)開放后倒是挺火的,許多第三方應(yīng)用都想試下接入微信這個(gè)平臺(tái),畢竟可以利用微信建立起來的關(guān)系鏈來拓展自己的應(yīng)用還是挺不錯(cuò)的 最近由于實(shí)習(xí)需要也在研究這個(gè)東西,這里把我的整個(gè)研究情況給出來2013-01-01Android 啟動(dòng) Service(startservice和bindservice) 兩種方式的區(qū)別
andrid service 兩種啟動(dòng)方式:第一種startservice,第二種bindservice,大家對(duì)這兩種啟動(dòng)方式的區(qū)別了解嗎,下面跟著小編一起學(xué)習(xí)吧2015-11-11玩轉(zhuǎn)Kotlin 徹底弄懂Lambda和高階函數(shù)
這篇文章主要幫助大家徹底弄懂Lambda和高階函數(shù),玩轉(zhuǎn)Kotlin,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android實(shí)現(xiàn)點(diǎn)擊Button產(chǎn)生水波紋效果
這篇文章主要介紹了Android實(shí)現(xiàn)點(diǎn)擊Button產(chǎn)生水波紋效果,需要的朋友可以參考下2016-01-01Android 實(shí)現(xiàn)左滑出現(xiàn)刪除選項(xiàng)
滑動(dòng)刪除的部分主要包含兩個(gè)部分, 一個(gè)是內(nèi)容區(qū)域(用于放置正常顯示的view),另一個(gè)是操作區(qū)域(用于放置刪除按鈕)。下面通過本文給大家介紹Android 實(shí)現(xiàn)左滑出現(xiàn)刪除選項(xiàng),需要的朋友可以參考下2017-06-06Android App中用Handler實(shí)現(xiàn)ViewPager頁面的自動(dòng)切換
這篇文章主要介紹了Android App中用Handler實(shí)現(xiàn)ViewPager頁面的自動(dòng)切換的方法,類似于相冊(cè)自動(dòng)播放,主要是切換后要提示當(dāng)前頁面所在的位置,需要的朋友可以參考下2016-05-05