上一節中,咱們講了 Flutter
中 Text
組件的一些用法以及 API
,本節咱們繼續學習 Flutter
中的 Image
組件,一樣先上圖:html
在 Android
中,咱們都知道,圖片的顯示方式有不少,資源圖片、網絡圖片、文件圖片等等,在 Flutter
中也有多種方式,用來加載不一樣形式的圖片:前端
Image
的一個參數是 ImageProvider
,基本上全部形式的圖片加載都是依賴它,這個類裏面就是實現圖片加載的原理。用法以下:git
new Image(image: new AssetImage('images/logo.png'));
new Image(image: new NetworkImage('http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg'))
複製代碼
加載一個本地資源圖片,和 Android
同樣,有多種分辨率的圖片可供選擇,可是沿襲的是 iOS
的圖片風格,分爲 1x
,2x
,3x
,具體作法是在項目的根目錄下建立兩個文件夾,以下圖所示:github
而後須要在 pubspec.yaml
文件中聲明一下:數組
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- images/logo.png
- images/2.0x/logo.png
- images/3.0x/logo.png
複製代碼
用法以下:緩存
new Image.asset('images/logo.png')
複製代碼
加載一個本地 File
圖片,好比相冊中的圖片,用法以下bash
new Image.file(new File('/storage/xxx/xxx/test.jpg'))
複製代碼
加載一個網絡圖片,用法以下:網絡
new Image.network('http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg')
複製代碼
有的時候咱們須要像Android那樣使用一個佔位圖或者圖片加載出錯時顯示某張特定的圖片,這時候須要用到 FadeInImage
這個組件:app
new FadeInImage.assetNetwork(
placeholder: 'images/logo.png',
image: imageUrl,
width: 120,
fit: BoxFit.fitWidth,
)
new FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageUrl,
width: 120,
fit: BoxFit.fitWidth,
)
複製代碼
第一種方法是加載一個本地的佔位圖,第二種是加載一個透明的佔位圖,可是須要注意的是,這個組件是不能夠設置加載出錯顯示的圖片的;這裏有另外一種方法可使用第三方 package
的 CachedNetworkImage
組件:less
new CachedNetworkImage(
width: 120,
fit: BoxFit.fitWidth,
placeholder: new CircularProgressIndicator(),
imageUrl: imageUrl,
errorWidget: new Icon(Icons.error),
)
複製代碼
CachedNetworkImage
組件中的佔位圖是一個 Widget
,這樣的話就能夠自定義了,你想使用什麼樣的組件進行佔位都行,一樣加載出錯的佔位圖也是一個組件,也能夠本身定義;該組件也是經過緩存來加載圖片的。
用來將一個 byte
數組加載成圖片,用法以下:
new Image.memory(bytes)
複製代碼
API名稱 | 功能 |
---|---|
width & height | 用來指定顯示圖片區域的寬高(並不是圖片的寬高) |
fit | 設置圖片填充,相似於Android中的ScaleType |
color & colorBlendMode | 這兩個屬性須要配合使用,就是顏色和圖片混合,就相似於Android中的Xfermode |
alignment | 用來控制圖片擺放的位置 |
repeat | 用來設置圖片重複顯示(repeat-x水平重複,repeat-y垂直重複,repeat兩個方向都重複,no-repeat默認狀況不重複) |
centerSlice | 設置圖片內部拉伸,至關於在圖片內部設置了一個.9圖,可是須要注意的是,要在顯示圖片的大小大於原圖的狀況下才可使用這個屬性,要否則會報錯 |
matchTextDirection | 這個須要配合Directionality進行使用 |
gaplessPlayback | 當圖片發生改變以後,從新加載圖片過程當中的樣式(一、原圖片保留) |
fit
屬性中有不少值能夠設置:
屬性名稱 | 樣式 |
---|---|
BoxFit.contain | 全圖居中顯示但不充滿,顯示原比例 |
BoxFit.cover | 圖片可能拉伸,也可能裁剪,可是充滿容器 |
BoxFit.fill | 全圖顯示且填充滿,圖片可能會拉伸 |
BoxFit.fitHeight | 圖片可能拉伸,可能裁剪,高度充滿 |
BoxFit.fitWidth | 圖片可能拉伸,可能裁剪,寬度充滿 |
BoxFit.scaleDown | 效果和contain差很少, 可是隻能縮小圖片,不能放大圖片 |
colorBlendMode
屬性中有不少值能夠設置,因爲可選值太多,這裏就不一一介紹了,有興趣的能夠去官網colorBlendMode屬性介紹看看
不少時候咱們須要給圖片設置圓角,那麼在flutter中是怎麼實現的呢?有不少種方法能夠實現,下面我舉兩個例子:
使用裁剪來實現圖片圓角:
new ClipRRect(
child: Image.network(
imageUrl,
scale: 8.5,
fit: BoxFit.cover,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
)
使用邊框來實現圖片圓角:
new Container(
width: 120,
height: 60,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
image: DecorationImage(
image: NetworkImage(imageUrl),
fit: BoxFit.cover),
),
)
複製代碼
須要注意的是,使用邊框實現的時候要注意設置 fit
屬性,否則效果也是有問題的,固然了你還可使用 Material
組件來實現,這個你們能夠本身去嘗試。
圓形圖片用得最多的應該是頭像之類的,這種一樣有多種方式能夠實現,下面我也舉兩個例子:
使用裁剪實現圓形圖片:
new ClipOval(
child: Image.network(
imageUrl,
scale: 8.5,
),
)
使用CircleAvatar來實現圓形圖片:
new CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
radius: 50.0,
)
複製代碼
固然了,你還可使用邊框 BoxDecoration
來實現,效果也是同樣的。
下面來看一下詳細的代碼實現:
class _ImageViewWidget extends State<ImageViewWidget> {
var imageUrl =
"http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg";
var imageUrl2 =
"http://n.sinaimg.cn/sports/2_img/upload/4f160954/107/w1024h683/20181128/Yrxn-hpinrya6814381.jpg";
@override
Widget build(BuildContext context) {
return new Align(
child: ListView(
children: <Widget>[
new Text('資源圖片:'),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Padding(
padding: const EdgeInsets.all(10.0),
child: Image.asset(
'images/logo.png',
),
),
// new Image.file(
// File('/storage/emulated/0/Download/test.jpg'),
// width: 120,
// //fill(全圖顯示且填充滿,圖片可能會拉伸),contain(全圖顯示但不充滿,顯示原比例),cover(顯示可能拉伸,也可能裁剪,充滿)
// //fitWidth(顯示可能拉伸,可能裁剪,寬度充滿),fitHeight顯示可能拉伸,可能裁剪,高度充滿),scaleDown(效果和contain差很少,可是)
// ),
],
),
new Text('網絡佔位圖片CachedNetworkImage:'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
imageUrl,
scale: 8.5,
),
new Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: CachedNetworkImage(
width: 120,
fit: BoxFit.fitWidth,
placeholder: Image(image: AssetImage('images/logo.png')),
imageUrl: imageUrl,
errorWidget: new Icon(Icons.error),
),
),
new CachedNetworkImage(
imageUrl: imageUrl,
width: 120,
fit: BoxFit.fitWidth,
placeholder: CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
)
],
),
),
new Text('網絡佔位圖片FadeInImage:'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: new Row(
children: <Widget>[
new FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageUrl,
width: 120,
fit: BoxFit.fitWidth,
),
new Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: new FadeInImage.assetNetwork(
placeholder: 'images/logo.png',
image: imageUrl,
width: 120,
fit: BoxFit.fitWidth,
),
),
],
mainAxisAlignment: MainAxisAlignment.center,
),
),
new Text('圓形圓角圖片:'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new ClipOval(
child: Image.network(
imageUrl,
width: 100,
height: 100,
fit: BoxFit.fitHeight,
),
),
new Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: ClipOval(
child: Image.asset(
'images/logo.png',
width: 100,
height: 100,
fit: BoxFit.fitHeight,
),
),
),
new ClipRRect(
child: Image.network(
imageUrl,
scale: 8.5,
fit: BoxFit.cover,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
)
],
),
),
new Text('顏色混合圖片:'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Image.asset(
'images/logo.png',
color: Colors.red,
colorBlendMode: BlendMode.darken,
),
new Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Image.network(
imageUrl,
scale: 8.5,
colorBlendMode: BlendMode.colorDodge,
color: Colors.blue,
),
),
],
),
),
new Text('centerSlice圖片內部拉伸:'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: new Image.asset(
'images/logo.png',
width: 250,
height: 250,
fit: BoxFit.contain,
centerSlice:
new Rect.fromCircle(center: const Offset(20, 20), radius: 1),
),
),
new Text('matchTextDirection圖片內部方向'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Directionality(
textDirection: TextDirection.ltr,
child: Image.network(
imageUrl,
height: 100,
matchTextDirection: true,
fit: BoxFit.fitHeight,
),
),
new Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Directionality(
textDirection: TextDirection.rtl,
child: Image.network(
imageUrl,
height: 100,
matchTextDirection: true,
fit: BoxFit.fitHeight,
),
),
),
],
),
),
new Text('點擊替換圖片'),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: Row(
children: <Widget>[
new RaisedButton(
onPressed: () {
setState(() {
widget.networkImage =
new NetworkImage(imageUrl2, scale: 8.5);
});
},
child: Text('點擊更換圖片'),
),
new Image(
gaplessPlayback: false,
fit: BoxFit.contain,
image: widget.networkImage,
),
],
),
)
],
),
);
}
}
複製代碼
代碼已上傳至Github
歡迎關注個人我的公衆號【IT先森養成記】,專一大前端技術分享,包含Android,Java,Kotlin,Flutter,HTML,CSS,JS等技術;在這裏你能獲得的不止是技術上的提高,還有一些學習經驗以及志同道合的朋友,趕快加入咱們,一塊兒學習,一塊兒進化吧!!!