Flutter實(shí)戰(zhàn) 圖片及ICON

2021-03-06 17:49 更新

#3.5.1 圖片

Flutter 中,我們可以通過Image組件來加載并顯示圖片,Image的數(shù)據(jù)源可以是 asset、文件、內(nèi)存以及網(wǎng)絡(luò)。

#ImageProvider

ImageProvider 是一個(gè)抽象類,主要定義了圖片數(shù)據(jù)獲取的接口load(),從不同的數(shù)據(jù)源獲取圖片需要實(shí)現(xiàn)不同的ImageProvider ,如AssetImage是實(shí)現(xiàn)了從 Asset 中加載圖片的 ImageProvider,而NetworkImage實(shí)現(xiàn)了從網(wǎng)絡(luò)加載圖片的 ImageProvider。

#Image

Image widget 有一個(gè)必選的image參數(shù),它對(duì)應(yīng)一個(gè) ImageProvider。下面我們分別演示一下如何從 asset 和網(wǎng)絡(luò)加載圖片。

#從asset中加載圖片

  1. 在工程根目錄下創(chuàng)建一個(gè)images目錄,并將圖片 avatar.png 拷貝到該目錄。

  1. pubspec.yaml中的flutter部分添加如下內(nèi)容:

  1. assets:
  2. - images/avatar.png

注意: 由于 yaml 文件對(duì)縮進(jìn)嚴(yán)格,所以必須嚴(yán)格按照每一層兩個(gè)空格的方式進(jìn)行縮進(jìn),此處assets前面應(yīng)有兩個(gè)空格。

  1. 加載該圖片

  1. Image(
  2. image: AssetImage("images/avatar.png"),
  3. width: 100.0
  4. );

Image 也提供了一個(gè)快捷的構(gòu)造函數(shù)Image.asset用于從 asset 中加載、顯示圖片:

  1. Image.asset("images/avatar.png",
  2. width: 100.0,
  3. )

#從網(wǎng)絡(luò)加載圖片

  1. Image(
  2. image: NetworkImage(
  3. "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
  4. width: 100.0,
  5. )

Image 也提供了一個(gè)快捷的構(gòu)造函數(shù)Image.network用于從網(wǎng)絡(luò)加載、顯示圖片:

  1. Image.network(
  2. "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
  3. width: 100.0,
  4. )

運(yùn)行上面兩個(gè)示例,圖片加載成功后如圖3-17所示:

圖3-17

#參數(shù)

Image在顯示圖片時(shí)定義了一系列參數(shù),通過這些參數(shù)我們可以控制圖片的顯示外觀、大小、混合效果等。我們看一下 Image 的主要參數(shù):

  1. const Image({
  2. ...
  3. this.width, //圖片的寬
  4. this.height, //圖片高度
  5. this.color, //圖片的混合色值
  6. this.colorBlendMode, //混合模式
  7. this.fit,//縮放模式
  8. this.alignment = Alignment.center, //對(duì)齊方式
  9. this.repeat = ImageRepeat.noRepeat, //重復(fù)方式
  10. ...
  11. })

  • width、height:用于設(shè)置圖片的寬、高,當(dāng)不指定寬高時(shí),圖片會(huì)根據(jù)當(dāng)前父容器的限制,盡可能的顯示其原始大小,如果只設(shè)置widthheight的其中一個(gè),那么另一個(gè)屬性默認(rèn)會(huì)按比例縮放,但可以通過下面介紹的fit屬性來指定適應(yīng)規(guī)則。

  • fit:該屬性用于在圖片的顯示空間和圖片本身大小不同時(shí)指定圖片的適應(yīng)模式。適應(yīng)模式是在BoxFit中定義,它是一個(gè)枚舉類型,有如下值:

  • fill:會(huì)拉伸填充滿顯示空間,圖片本身長(zhǎng)寬比會(huì)發(fā)生變化,圖片會(huì)變形。
  • cover:會(huì)按圖片的長(zhǎng)寬比放大后居中填滿顯示空間,圖片不會(huì)變形,超出顯示空間部分會(huì)被剪裁。
  • contain:這是圖片的默認(rèn)適應(yīng)規(guī)則,圖片會(huì)在保證圖片本身長(zhǎng)寬比不變的情況下縮放以適應(yīng)當(dāng)前顯示空間,圖片不會(huì)變形。
  • fitWidth:圖片的寬度會(huì)縮放到顯示空間的寬度,高度會(huì)按比例縮放,然后居中顯示,圖片不會(huì)變形,超出顯示空間部分會(huì)被剪裁。
  • fitHeight:圖片的高度會(huì)縮放到顯示空間的高度,寬度會(huì)按比例縮放,然后居中顯示,圖片不會(huì)變形,超出顯示空間部分會(huì)被剪裁。
  • none:圖片沒有適應(yīng)策略,會(huì)在顯示空間內(nèi)顯示圖片,如果圖片比顯示空間大,則顯示空間只會(huì)顯示圖片中間部分。

一圖勝萬言! 我們對(duì)一個(gè)寬高相同的頭像圖片應(yīng)用不同的fit值,效果如圖3-18所示:

圖3-18

  • colorcolorBlendMode:在圖片繪制時(shí)可以對(duì)每一個(gè)像素進(jìn)行顏色混合處理,color指定混合色,而colorBlendMode指定混合模式,下面是一個(gè)簡(jiǎn)單的示例:

  1. Image(
  2. image: AssetImage("images/avatar.png"),
  3. width: 100.0,
  4. color: Colors.blue,
  5. colorBlendMode: BlendMode.difference,
  6. );

運(yùn)行效果如圖3-19所示(彩色):

圖3-19

  • repeat:當(dāng)圖片本身大小小于顯示空間時(shí),指定圖片的重復(fù)規(guī)則。簡(jiǎn)單示例如下:

  1. Image(
  2. image: AssetImage("images/avatar.png"),
  3. width: 100.0,
  4. height: 200.0,
  5. repeat: ImageRepeat.repeatY ,
  6. )

運(yùn)行后效果如圖3-20所示:

圖3-20

完整的示例代碼如下:

  1. import 'package:flutter/material.dart';
  2. class ImageAndIconRoute extends StatelessWidget {
  3. @override
  4. Widget build(BuildContext context) {
  5. var img=AssetImage("imgs/avatar.png");
  6. return SingleChildScrollView(
  7. child: Column(
  8. children: <Image>[
  9. Image(
  10. image: img,
  11. height: 50.0,
  12. width: 100.0,
  13. fit: BoxFit.fill,
  14. ),
  15. Image(
  16. image: img,
  17. height: 50,
  18. width: 50.0,
  19. fit: BoxFit.contain,
  20. ),
  21. Image(
  22. image: img,
  23. width: 100.0,
  24. height: 50.0,
  25. fit: BoxFit.cover,
  26. ),
  27. Image(
  28. image: img,
  29. width: 100.0,
  30. height: 50.0,
  31. fit: BoxFit.fitWidth,
  32. ),
  33. Image(
  34. image: img,
  35. width: 100.0,
  36. height: 50.0,
  37. fit: BoxFit.fitHeight,
  38. ),
  39. Image(
  40. image: img,
  41. width: 100.0,
  42. height: 50.0,
  43. fit: BoxFit.scaleDown,
  44. ),
  45. Image(
  46. image: img,
  47. height: 50.0,
  48. width: 100.0,
  49. fit: BoxFit.none,
  50. ),
  51. Image(
  52. image: img,
  53. width: 100.0,
  54. color: Colors.blue,
  55. colorBlendMode: BlendMode.difference,
  56. fit: BoxFit.fill,
  57. ),
  58. Image(
  59. image: img,
  60. width: 100.0,
  61. height: 200.0,
  62. repeat: ImageRepeat.repeatY ,
  63. )
  64. ].map((e){
  65. return Row(
  66. children: <Widget>[
  67. Padding(
  68. padding: EdgeInsets.all(16.0),
  69. child: SizedBox(
  70. width: 100,
  71. child: e,
  72. ),
  73. ),
  74. Text(e.fit.toString())
  75. ],
  76. );
  77. }).toList()
  78. ),
  79. );
  80. }
  81. }

#Image緩存

Flutter 框架對(duì)加載過的圖片是有緩存的(內(nèi)存),默認(rèn)最大緩存數(shù)量是1000,最大緩存空間為 100M。關(guān)于 Image 的詳細(xì)內(nèi)容及原理我們將會(huì)在后面進(jìn)階部分深入介紹。

#3.5.2 ICON

Flutter 中,可以像Web開發(fā)一樣使用 iconfont,iconfont 即“字體圖標(biāo)”,它是將圖標(biāo)做成字體文件,然后通過指定不同的字符而顯示不同的圖片。

在字體文件中,每一個(gè)字符都對(duì)應(yīng)一個(gè)位碼,而每一個(gè)位碼對(duì)應(yīng)一個(gè)顯示字形,不同的字體就是指字形不同,即字符對(duì)應(yīng)的字形是不同的。而在 iconfont 中,只是將位碼對(duì)應(yīng)的字形做成了圖標(biāo),所以不同的字符最終就會(huì)渲染成不同的圖標(biāo)。

在 Flutter 開發(fā)中,iconfont 和圖片相比有如下優(yōu)勢(shì):

  1. 體積?。嚎梢詼p小安裝包大小。
  2. 矢量的:iconfont 都是矢量圖標(biāo),放大不會(huì)影響其清晰度。
  3. 可以應(yīng)用文本樣式:可以像文本一樣改變字體圖標(biāo)的顏色、大小對(duì)齊等。
  4. 可以通 過TextSpan 和文本混用。

#使用Material Design字體圖標(biāo)

Flutter 默認(rèn)包含了一套 Material Design 的字體圖標(biāo),在pubspec.yaml文件中的配置如下

  1. flutter:
  2. uses-material-design: true

Material Design 所有圖標(biāo)可以在其官網(wǎng)查看:https://material.io/tools/icons/

我們看一個(gè)簡(jiǎn)單的例子:

  1. String icons = "";
  2. // accessible:  or 0xE914 or E914
  3. icons += "\uE914";
  4. // error:  or 0xE000 or E000
  5. icons += " \uE000";
  6. // fingerprint:  or 0xE90D or E90D
  7. icons += " \uE90D";
  8. Text(icons,
  9. style: TextStyle(
  10. fontFamily: "MaterialIcons",
  11. fontSize: 24.0,
  12. color: Colors.green
  13. ),
  14. );

運(yùn)行效果如圖3-21所示:

通過這個(gè)示例可以看到,使用圖標(biāo)就像使用文本一樣,但是這種方式需要我們提供每個(gè)圖標(biāo)的碼點(diǎn),這并對(duì)開發(fā)者不友好,所以,F(xiàn)lutter 封裝了IconDataIcon來專門顯示字體圖標(biāo),上面的例子也可以用如下方式實(shí)現(xiàn):

  1. Row(
  2. mainAxisAlignment: MainAxisAlignment.center,
  3. children: <Widget>[
  4. Icon(Icons.accessible,color: Colors.green,),
  5. Icon(Icons.error,color: Colors.green,),
  6. Icon(Icons.fingerprint,color: Colors.green,),
  7. ],
  8. )

Icons類中包含了所有 Material Design 圖標(biāo)的IconData靜態(tài)變量定義。

#使用自定義字體圖標(biāo)

我們也可以使用自定義字體圖標(biāo)。iconfont.cn 上有很多字體圖標(biāo)素材,我們可以選擇自己需要的圖標(biāo)打包下載后,會(huì)生成一些不同格式的字體文件,在 Flutter 中,我們使用 ttf 格式即可。

假設(shè)我們項(xiàng)目中需要使用一個(gè)書籍圖標(biāo)和微信圖標(biāo),我們打包下載后導(dǎo)入:

  1. 導(dǎo)入字體圖標(biāo)文件;這一步和導(dǎo)入字體文件相同,假設(shè)我們的字體圖標(biāo)文件保存在項(xiàng)目根目錄下,路徑為"fonts/iconfont.ttf":

  1. fonts:
  2. - family: myIcon #指定一個(gè)字體名
  3. fonts:
  4. - asset: fonts/iconfont.ttf

  1. 為了使用方便,我們定義一個(gè)MyIcons類,功能和Icons類一樣:將字體文件中的所有圖標(biāo)都定義成靜態(tài)變量:

  1. class MyIcons{
  2. // book 圖標(biāo)
  3. static const IconData book = const IconData(
  4. 0xe614,
  5. fontFamily: 'myIcon',
  6. matchTextDirection: true
  7. );
  8. // 微信圖標(biāo)
  9. static const IconData wechat = const IconData(
  10. 0xec7d,
  11. fontFamily: 'myIcon',
  12. matchTextDirection: true
  13. );
  14. }

  1. 使用

  1. Row(
  2. mainAxisAlignment: MainAxisAlignment.center,
  3. children: <Widget>[
  4. Icon(MyIcons.book,color: Colors.purple,),
  5. Icon(MyIcons.wechat,color: Colors.green,),
  6. ],
  7. )

運(yùn)行后效果如圖3-22所示:

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)