老孟導讀:你們好,這是【Flutter實戰】系列文章的第三篇,這一篇講解圖片組件,Image有不少高級用法,但願對您有所幫助。
圖片組件是Flutter基礎組件之一,和文本組件同樣必不可少。圖片組件包含Image和Icon兩個組件,本質上Icon不屬於圖片組件,但其外形效果上相似於圖片。html
在項目中建議優先使用Icon組件,Icon本質上是一種字體,只不過顯示的不是文字,而是圖標,而Image組件先經過圖片解碼器將圖片解碼,因此Icon有以下優勢:git
Image組件用於顯示圖片,圖片的來源能夠是網絡、項目中圖片或者設備上的圖片。github
加載網絡圖片:算法
Image.network( 'http://pic1.win4000.com/pic/c/cf/cdc983699c.jpg', )
加載項目中圖片:api
首先將圖片拷貝到項目中,一般狀況下,拷貝到assets/images/
目錄下,assets/images/
目錄爲手動建立,新建的項目默認是沒有此目錄的。微信
設置pubspec.yaml
配置文件:網絡
assets: - assets/images/
或者指定具體圖片的名稱:app
assets: - assets/images/aa.jpg
一般狀況下,使用第一種方式,由於圖片會有不少張,增長一張就這裏配置一個太麻煩。ide
注意:assets前面的空格問題,極容易引起編譯異常,正確格式以下:性能
加載圖片:
Image.asset('assets/images/aa.jpg')
加載設備上的圖片:
要加載設備(手機)上的圖片首先須要獲取設備圖片的路徑,因爲不一樣平臺的路徑不一樣,所以路徑的獲取必須依靠原生支持,若是瞭解原生(Android和iOS)開發,能夠直接使用MethodChannel獲取路徑,若是不懂原生(Android和iOS)開發,可使用第三方插件獲取路徑,這裏推薦官方的path_provider。
加載設備上的圖片:
Image.file(File('path'))
設置圖片的大小:
Image.asset('assets/images/aa.jpg',width: 100,height: 200,),
當Image的大小和圖片大小不匹配時,須要設置填充模式fit
,設置組件大小爲150x150,
Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150), )
看到,圖片左右兩邊有空白區域(淺紅色填充的區域),若是想要圖片充滿整個區域,設置以下:
Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150,fit: BoxFit.fill,), )
雖然圖片充滿整個區域,但圖片變形了,使圖片等比拉伸,直到兩邊都充滿區域:
Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150,fit: BoxFit.cover,), )
此時,圖片未變形且兩邊都充滿區域,不過圖片被裁減了一部分。
fit
參數就是設置填充方式,其值介紹以下:
BoxFit.none
的裁減和alignment
相關,默認居中,
Image.asset( 'assets/images/aa.jpg', width: 150, height: 150, fit: BoxFit.none, alignment: Alignment.centerRight, ),
左邊爲原圖。
設置對齊方式:
Container( color: Colors.red.withOpacity(.3), child: Image.asset( 'assets/images/aa.jpg', width: 150, height: 150, alignment: Alignment.centerLeft, ), ),
color
和colorBlendMode
用於將顏色和圖片進行顏色混合,colorBlendMode
表示混合模式,下面介紹的混合模式比較多,瀏覽一遍便可,此屬性能夠用於簡單的濾鏡效果。
是否是感受看了和沒看差很少,看了也看不懂。正常,估計只有學過視覺算法的才能看懂吧,直接看下各個屬性的效果吧:
repeat
表示當組件有空餘位置時,將會重複顯示圖片
Image.asset( 'assets/images/aa.jpg', width: double.infinity, height: 150, repeat: ImageRepeat.repeatX, )
重複的模式有:
matchTextDirection
設置爲true時,圖片的繪製方向爲TextDirection設置的方向,其父組件必須爲Directionality:
Directionality( textDirection: TextDirection.rtl, child: Image.asset( 'assets/images/logo.png', height: 150, matchTextDirection: true, )),
左邊爲原圖,效果是左右鏡像。
filterQuality
表示繪製圖像的質量,從高到低爲:high->medium->low->none。越高效果越好,越平滑,固然性能損耗越大,默認是low
,若是發現圖片有鋸齒,能夠設置此參數。
當加載圖片的時候回調frameBuilder
,當此參數爲null時,此控件將會在圖片加載完成後顯示,未加載完成時顯示空白,尤爲在加載網絡圖片時會更明顯。所以此參數能夠用於處理圖片加載時顯示佔位圖片和加載圖片的過渡效果,好比淡入淡出效果。
下面的案例是淡入淡出效果:
Image.network( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg', frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) { if (wasSynchronouslyLoaded) { return child; } return AnimatedOpacity( child: child, opacity: frame == null ? 0 : 1, duration: const Duration(seconds: 2), curve: Curves.easeOut, ); }, )
loadingBuilder
參數比frameBuilder
控制的力度更細,能夠獲取圖片加載的進度,下面的案例顯示了加載進度條:
Image.network( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg', loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) { if (loadingProgress == null) { return child; } return Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes : null, ), ); })
centerSlice
用於.9圖,.9圖用於拉伸圖片的特定區域,centerSlice
設置的區域(Rect)就是拉伸的區域。.9圖一般用於控件大小、寬高比不固定的場景,好比聊天背景圖片等。
Container( width: 250, height: 300, decoration: BoxDecoration( image: DecorationImage( centerSlice: Rect.fromLTWH(20, 20, 10, 10), image: AssetImage( 'assets/images/abc.jpg', ), fit: BoxFit.fill))),
上面爲原圖,下面爲拉伸的圖片。
在使用時大機率會出現以下異常:
這是因爲圖片比組件的尺寸大,若是使用centerSlice
屬性,圖片必須比組件的尺寸小,通常狀況下,.9圖的尺寸都很是小。
Icon是圖標組件,Icon不具備交互屬性,若是想要交互,可使用IconButton。
Icon(Icons.add),
設置圖標的大小和顏色:
Icon( Icons.add, size: 40, color: Colors.red, )
上面的黑色爲默認大小和顏色。
Icons.add
是系統提供的圖標,建立Flutter項目的時候,pubspec.yaml
中默認有以下配置:
全部的圖標在Icons中已經定義,能夠直接在源代碼中查看,也能夠到官網查看全部圖標。
全部圖標效果以下:
Container( width: 200, padding: EdgeInsets.only(left: 8,top: 8,right: 20,bottom: 8), decoration: BoxDecoration( image: DecorationImage( centerSlice: Rect.fromLTWH(20, 20, 1, 1), image: AssetImage( 'assets/images/chat.png', ), fit: BoxFit.fill)), child: Text('老孟,專一分享Flutter技術和應用實戰。' '老孟,專一分享Flutter技術和應用實戰。' '老孟,專一分享Flutter技術和應用實戰。',), )
背景圖片大小是57x80:
右側三角已經不在中間了,若是想讓其一直保持居中,修改拉伸區域:
centerSlice: Rect.fromLTWH(20, 10, 1, 60),
Container( width: 100, height: 100, padding: EdgeInsets.all(3), decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.blue), child: Container( decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: AssetImage('assets/images/aa.jpg'), fit: BoxFit.cover)), ), )
Image.network( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg', height: 150, width: 150, fit: BoxFit.cover, frameBuilder: ( BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded, ) { if (frame == null) { return Image.asset( 'assets/images/place.png', height: 150, width: 150, fit: BoxFit.cover, ); } return child; }, )
若是系統提供的圖標沒有咱們想要的圖標,這時須要引入第三方庫的圖標,下面以阿里巴巴的圖標庫爲例。
打開阿里巴巴的圖標官網,找到本身想要的圖標後,將鼠標放置到圖標上,加入購物車:
點擊右上角的購物車,而後點擊添加至項目:
<img src="http://img.laomengit.com/iconfont_2.png" style="zoom:33%;" />
若是沒有添加過項目,須要建立一個新項目:
<img src="http://img.laomengit.com/iconfont_3.png" style="zoom:33%;" />
建立好後加入此項目,跳轉到個人項目
頁面,點擊下載:
解壓下載的文件,解壓出來的文件有好幾個,以下圖:
選擇iconfont.ttf
文件拷貝到 Flutter 項目的assets/fonts
目錄下,assets/fonts
目錄默認是沒有的,須要手動建立,在pubspec.yaml
設置以下:
<img src="http://img.laomengit.com/iconfont_6.png" style="zoom:50%;" />
千萬注意紅框內開頭的空格問題,不然編譯不經過,family
後面跟的字符串最好有意義,後面用圖標的時候須要用到。
用法以下:
Icon(IconData(0xe613,fontFamily: 'appIconFonts')
0xe613
在下載圖標時已經標註,將&#
替換爲0
,以下圖:
fontFamily
是在pubspec.yaml
中設置的family
屬性,第三方的圖標和系統圖標同樣,能夠設置其顏色和大小。
老孟Flutter博客地址(330個控件用法):http://laomengit.com
歡迎加入Flutter交流羣(微信:laomengit)、關注公衆號【老孟Flutter】: