Flutter中薪前,可以通過Image組件來加載并顯示圖片,Image的數(shù)據(jù)源可以是asset柴淘、文件迫淹、內(nèi)存以及網(wǎng)絡(luò)秘通。
- ImageProvider
ImageProvider是一個抽象類,主要定義了圖片數(shù)據(jù)獲取的接口load()敛熬,從不同的數(shù)據(jù)源獲取圖片需要實現(xiàn)不同的ImageProvider 肺稀,如AssetImage是實現(xiàn)了從Asset中加載圖片的ImageProvider,而NetworkImage實現(xiàn)了從網(wǎng)絡(luò)加載圖片的ImageProvider应民』霸可以自行查閱文檔ImageProvider
1.從asset中加載圖片
在工程根目錄下創(chuàng)建一個文件夾,并將圖片拷貝到文件夾诲锹。在pubspec.yaml中的flutter部分添加如下內(nèi)容:
assets:
- assets/images/avatar.png
然后執(zhí)行flutter pub get
繁仁。
ps:yaml文件對縮進嚴格,所以必須嚴格按照每一層兩個空格的方式進行縮進归园,此處assets前面應(yīng)有兩個空格黄虱。筆者習慣創(chuàng)建兩層文件夾assets放圖片資源、字體資源等庸诱,images專門放圖片資源捻浦,所以在pubspec.yaml中配置assets/images/avatar.png
加載圖片代碼示例如下:
class AssetImageDefault1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Image(
image: AssetImage('assets/images/avatar.png'),
width: 200,
height: 200,
alignment: Alignment.center,
);
}
}
Image也提供了一個快捷的構(gòu)造函數(shù)Image.asset用于顯示圖片,代碼示例如下:
class ImageAssetDefault2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Image.asset(
'assets/images/avatar.png',
width: 200,
height: 200,
alignment: Alignment.center,
);
}
}
運行上面兩個示例桥爽,效果圖如下:如果加載時報錯找不到圖片資源朱灿,有可能是兩個原因:
1.pubspec.yaml中書寫不規(guī)范。不規(guī)范的縮進和字符都可能導致配置的內(nèi)容不生效钠四。要注意yaml的一個縮進是2個空格盗扒。如下圖所示:
2.代碼中的圖片相對路徑要和工程中實際路徑不一致。例如:項目flutter_demo/assets/images/demo.png形导,引用路徑:
AssetImage('assets/images/demo.png')
2.從網(wǎng)絡(luò)加載圖片
代碼示例如下:
class ImageNetWorkDefault1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Image(
image: NetworkImage(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg'),
width: 200,
height: 200,
alignment: Alignment.center,
);
}
}
Image也提供了一個快捷的構(gòu)造函數(shù)Image.network用于加載網(wǎng)絡(luò)圖片,代碼示例如下:
class ImageNetWorkDefault2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Image.network(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg',
width: 200,
height: 200,
);
}
}
代碼運行效果圖如下:3.參數(shù)
Image在顯示圖片時定義了一系列參數(shù)习霹,通過這些參數(shù)可以控制圖片的顯示外觀朵耕、大小、混合效果等淋叶。Image的主要參數(shù)如下:
const Image({
...
this.width, // 圖片的寬
this.height, // 圖片高度
this.color, // 圖片的混合色值
this.colorBlendMode, // 混合模式
this.fit,// 縮放模式
this.alignment = Alignment.center, // 對齊方式
this.repeat = ImageRepeat.noRepeat, // 重復方式
...
})
- width height
用于設(shè)置圖片的寬阎曹、高,當不指定寬高時煞檩,圖片會根據(jù)當前父容器的限制处嫌,盡可能的顯示其原始大小,如果只設(shè)置width斟湃、height的其中一個熏迹,那么另一個屬性默認會按比例縮放,可以通過fit屬性來指定適應(yīng)規(guī)則凝赛。 - fit
該屬性用于在圖片的顯示空間和圖片本身大小不同時指定圖片的適應(yīng)模式注暗。適應(yīng)模式是在BoxFit中定義坛缕,它是一個枚舉類型,有如下值:
fill:會拉伸填充滿顯示空間捆昏,圖片本身長寬比會發(fā)生變化,圖片會變形。
cover:會按圖片的長寬比放大后居中填滿顯示空間归形,圖片不會變形震庭,超出顯示空間部分會被剪裁。
contain:圖片的默認適應(yīng)規(guī)則寇仓,圖片會在保證圖片本身長寬比不變的情況下縮放以適應(yīng)當前顯示空間举户,圖片不會變形。
fitWidth:圖片的寬度會縮放到顯示空間的寬度焚刺,高度會按比例縮放敛摘,然后居中顯示,圖片不會變形乳愉,超出顯示空間部分會被剪裁兄淫。
fitHeight:圖片的高度會縮放到顯示空間的高度,寬度會按比例縮放蔓姚,然后居中顯示捕虽,圖片不會變形,超出顯示空間部分會被剪裁坡脐。
none:圖片沒有適應(yīng)策略泄私,會在顯示空間內(nèi)顯示圖片,如果圖片比顯示空間大备闲,則顯示空間只會顯示圖片中間部分晌端。
下面例子是對一個寬高相同的圖片應(yīng)用不同的fit值,代碼示例如下:
class FitImageDemo extends StatelessWidget {
final imageName = 'assets/images/avatar.png';
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Image>[
Image.asset(
imageName,
height: 50,
width: 50,
fit: BoxFit.fill,
),
Image.asset(
imageName,
height: 50,
width: 50,
fit: BoxFit.contain,
),
Image.asset(
imageName,
width: 100,
height: 50,
fit: BoxFit.cover,
),
Image.asset(
imageName,
width: 100,
height: 50,
fit: BoxFit.fitWidth,
),
Image.asset(
imageName,
width: 100,
height: 50,
fit: BoxFit.fitHeight,
),
Image.asset(
imageName,
width: 100,
height: 50,
fit: BoxFit.scaleDown,
),
Image.asset(
imageName,
width: 100,
height: 50,
fit: BoxFit.none,
),
].map((e) {
return Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(16.0),
child: SizedBox(
width: 100,
child: e,
),
),
Text(e.fit.toString()),
],
);
}).toList(),
),
);
}
}
代碼運行效果圖如下:- color colorBlendMode
在圖片繪制時可以對每一個像素進行顏色混合處理恬砂,color指定混合色咧纠,colorBlendMode指定混合模式,代碼示例:
Image.asset(
'assets/images/avatar.png',
width: 100,
color: Colors.blue,
colorBlendMode: BlendMode.difference,
),
運行效果如下:- repeat
當圖片本身大小小于顯示空間時泻骤,指定圖片的重復規(guī)則漆羔。代碼示例如下:
Image.asset(
'assets/images/avatar.png',
width: 100,
height: 200,
repeat: ImageRepeat.repeatY,
),
代碼運行效果圖如下:4.實現(xiàn)圓角圖像
實現(xiàn)圓角圖像有多種方式。
- CircleAvatar
CircleAvatar可以實現(xiàn)圓角頭像狱掂,也可以添加一個子Widget演痒。源碼如下:
const CircleAvatar({
Key key,
this.child, // 子Widget
this.backgroundColor, // 背景顏色
this.backgroundImage, // 背景圖像
this.foregroundColor, // 前景顏色
this.radius, // 半徑
this.minRadius, // 最小半徑
this.maxRadius, // 最大半徑
})
代碼示例如下:
class CircleAvatarImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CircleAvatar(
radius: 100,
backgroundImage: NetworkImage(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg'),
child: Container(
alignment: Alignment.center,
width: 100,
height: 100,
child: Text('貓頭鷹'),
),
);
}
}
運行效果圖如下:- ClipOval
ClipOval也可以實現(xiàn)圓角頭像,通常是在只有頭像時使用趋惨。代碼示例如下:
class ClipOvalImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ClipOval(
child: Image.network(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg',
width: 100,
height: 100,
),
);
}
}
運行效果圖如下:- ClipRRect
ClipRRect用于實現(xiàn)圓角效果鸟顺,可以設(shè)置圓角的大小。代碼示例如下:
class ClipRRectImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.network(
'https://tva1.sinaimg.cn/large/006y8mN6gy1g7aa03bmfpj3069069mx8.jpg',
width: 100,
height: 100,
),
);
}
}
運行效果圖如下:5.加載網(wǎng)絡(luò)圖片時顯示占位圖
加載網(wǎng)絡(luò)圖片時顯示占位圖可以用FadeInImage
器虾,部分源碼如下:
const FadeInImage({
@required this.placeholder,
@required this.image,
this.fadeOutDuration = const Duration(milliseconds: 300),
this.fadeInDuration = const Duration(milliseconds: 700),
this.width,
this.height,
...
})
/// Image displayed while the target [image] is loading.
final ImageProvider placeholder;
/// The target image that is displayed once it has loaded.
final ImageProvider image;
- placeholder
默認顯示的占位圖 - image
真正顯示的圖片 - fadeOutDuration fadeOutDuration
placeholder消失image顯示的過程有一個淡進淡出诊沪,fadeOutDuration和fadeOutDuration就是設(shè)置淡進淡出的時間养筒,不想那個要這種效果將Duration設(shè)置1毫秒,不可以設(shè)置為0端姚。
代碼示例如下:
class FadeImageDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: FadeInImage(
placeholder: AssetImage('assets/images/avatar.png'),
image: NetworkImage(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg'),
fadeInDuration: Duration(milliseconds: 1),
fadeOutDuration: Duration(milliseconds: 1),
width: 200,
height: 200,
),
);
}
}
但是這種方法沒有緩存每次都需要一段時間加載網(wǎng)絡(luò)圖片晕粪,cached_network_image 這個庫實現(xiàn)了圖片緩存加載和占位圖效果,可自行查閱文檔渐裸。