公衆號「AndroidTraveler」首發。git
對於設置控件寬度填充父控件這件事情,在 Android 裏面,只須要設置 MATCH_PARENT 便可。github
可是在 Flutter 裏面卻不是這樣,由於 Flutter 要具體的數值。api
因此咱們能夠這樣考慮,假設我這個值很是大,比全部市面上的設備寬度還要大,那麼是否是表現出來就是充滿父控件了。app
因此這邊的作法是設置爲無限,即 double.infiniteless
咱們以一個經常使用場景來講明。ide
好比設置圖片填充屏幕寬度。測試
剛開始沒有設置的代碼以下:ui
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('My Flutter'), ), body: Center( child: Image.asset('assets/images/example.jpeg'), ), ) ); } }
效果:this
能夠看到沒有設置的狀況下,顯示會根據圖片自身的寬高顯示。spa
這個時候若是設置 width 爲無窮大,修改代碼以下:
child: Image.asset('assets/images/example.jpeg', width: double.infinity,),
效果
什麼狀況,沒起做用?
這個時候不要慌,咱們來給你們分析分析。
之後你們遇到相似問題也能夠這樣分析。
咱們經過給 Image 外面套上一層 Container,而後設置背景顏色來對比一下。
代碼以下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('My Flutter'), ), body: Center( child: Container( color: Colors.blue, //left // child: Image.asset('assets/images/example.jpeg',), //right child: Image.asset('assets/images/example.jpeg', width: double.infinity,), ), ), )); } }
效果以下:
能夠看到,設置寬度以後,Image 確實是填充了寬度,只不過因爲圖片自己沒有那麼寬,所以看起來就覺得是沒有起做用。
那麼如何讓圖片能夠填充寬度呢?
這個就涉及到圖片的填充模式了。
點擊 Image 的 fit 屬性進入源碼能夠看到以下:
/// How to inscribe the image into the space allocated during layout. /// /// The default varies based on the other fields. See the discussion at /// [paintImage]. final BoxFit fit;
咱們再點一下 BoxFit,能夠看到以下:
/// How a box should be inscribed into another box. /// /// See also [applyBoxFit], which applies the sizing semantics of these values /// (though not the alignment semantics). enum BoxFit { /// Fill the target box by distorting the source's aspect ratio. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fill.png) fill, /// As large as possible while still containing the source entirely within the /// target box. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_contain.png) contain, /// As small as possible while still covering the entire target box. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_cover.png) cover, /// Make sure the full width of the source is shown, regardless of /// whether this means the source overflows the target box vertically. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitWidth.png) fitWidth, /// Make sure the full height of the source is shown, regardless of /// whether this means the source overflows the target box horizontally. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitHeight.png) fitHeight, /// Align the source within the target box (by default, centering) and discard /// any portions of the source that lie outside the box. /// /// The source image is not resized. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_none.png) none, /// Align the source within the target box (by default, centering) and, if /// necessary, scale the source down to ensure that the source fits within the /// box. /// /// This is the same as `contain` if that would shrink the image, otherwise it /// is the same as `none`. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_scaleDown.png) scaleDown, }
相信你們看到源碼的註釋應該很清楚每一個值的意義了。
若是你還不清楚,能夠點擊註釋裏面對應的連接去查看示意圖。
好比以咱們這個實際應用場景填充寬度爲例,那麼咱們能夠看到 fitWidth 應該是符合咱們要求的,咱們點擊註釋的連接,跳轉能夠看到圖片以下:
很形象的作了幾種狀況的示意。咱們設置了 Image 的 fit 屬性以下:
child: Image.asset('assets/images/example.jpeg', width: double.infinity, fit: BoxFit.fitWidth,),
效果:
能夠看到已經知足咱們的需求了。
舒適提示:測試完以後不要忘記去掉測試的 Container 以及對應顏色哦~
咱們知道在 Android 裏面,當咱們 try catch 以後,咱們打印異常基本會寫出相似下面代碼:
Log.e(TAG, "exception="+e);
在 Flutter 也有異常捕獲。
你可能會習慣的寫出以下代碼:
print('exception='+e);
可是切記,不要使用上面的寫法。
由於當 e 爲 null 時,上面的 print 不會執行打印。
這可能會誤導你。由於你在成功的時候加上打印語句,異常捕獲也加上打印語句。可是程序就是沒有打印。你就會以爲很奇怪。
實際上當 e 爲 null 時,print 語句會報錯,+ 號鏈接的左右不能是 null,因此不會正常打印。所以請避免上面的寫法。能夠用下面的替換寫法:
//替換寫法一 print('exception='); print(e); //替換寫法二 print('exception='+(e ?? '')); //替換寫法三 var printContent = e ?? ''; print('exception='+printContent);
咱們知道若是要給一個 Widget 增長點擊事件,最簡單的方法就是套一層 GestureDetector。
可是有時候你這樣作了,卻發現有些「隱患」,或者說,有些你意料不到的事情。
這裏用一個場景來告訴你,你平時可能沒有發現的細節。
微博裏面有點贊這個小組件,咱們寫下以下代碼:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('My Flutter'), ), body: Row( children: <Widget>[ Image.asset('assets/images/2.0x/like.png', width: 20, height: 20,), SizedBox(width: 5,), Text('30') ], ), )); } }
效果以下:
假設咱們要求給這個點贊組件加上點擊事件,那麼咱們直接給 Row 套上 GestureDetector Widget。
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('My Flutter'), ), body: GestureDetector( onTap: (){ print('onTap'); }, child: Row( children: <Widget>[ Image.asset('assets/images/2.0x/like.png', width: 20, height: 20,), SizedBox(width: 5,), Text('30') ], ), ), )); } }
點擊點贊組件確實會打印 onTap,可是若是你點擊了點贊圖標和數字中間的白色區域,你會發現點擊事件沒有回調,沒有打印。
這個時候有兩種解決方法:
1. 給空白組件設置 color 屬性,顏色值設置透明
對於 Container 設置的 padding 能夠直接設置,對於咱們這裏例子的 SizeBox 須要改成以下:
SizedBox(width: 15, child: Container(color: Colors.transparent,),),
爲了方便測試,這邊將寬度改成 15。
因此對於設置 GestureDetector 的 Container,若是沒有設置 color 屬性,那麼點擊空白不會回調。
2. 設置 GestureDetector 的 behavior 屬性(推薦方式)
其實若是你須要空白區域也響應點擊,只須要設置一下 GestureDetector 的 behavior 屬性便可。
behavior 默認值爲 HitTestBehavior.deferToChild,咱們這裏將其設置爲 HitTestBehavior.translucent。
代碼以下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('My Flutter'), ), body: GestureDetector( behavior: HitTestBehavior.translucent, onTap: (){ print('onTap'); }, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Image.asset('assets/images/2.0x/like.png', width: 20, height: 20,), SizedBox(width: 15), Text('30') ], ), ), )); } }
這裏的點贊圖片我直接從網上獲取的,你測試能夠用隨便一張圖片代替驗證。或者用兩個文原本驗證也是能夠的。