Flutter 基礎元件之 Image
正所謂一圖勝千言,一張意思清晰明瞭的圖片勝過 N 句廢話,所以圖片的展示是相當重要的,Image 是 Flutter 用於展示圖片的控制元件,它可以載入專案內的圖片、手機儲存中的圖片以及直接從網路載入圖片,不用再整合圖片載入框架就可以載入網路圖片這就很方便了。
1 構造方法
Image({Key key, @required ImageProvider image, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })
建立一個 Image 元件,其中一個必傳引數為 ImageProvider,它指定了圖片是從哪裡載入,是從專案中還是網路中等等。
Image.asset(String name, { Key key, AssetBundle bundle, String semanticLabel, bool excludeFromSemantics: false, double scale, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, String package, FilterQuality filterQuality: FilterQuality.low })
建立一個從專案中的資源目錄載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 AssetImage。
Image.file(File file, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })
建立一個從手機儲存目錄載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 FlieImage。
Image.memory(Uint8List bytes, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })
應該是建立一個從記憶體或者位元組流載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 MemoryImage。
Image.network(String src, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low, Map<String, String> headers })
建立一個從網路載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 NetworkImage。
其實後四種構造方法就相當於對第一種構造方法進行了封裝,不用傳入 ImageProvider 而已,但是仍要傳入圖片路徑,所以說也沒省多大事,我比較傾向用第一種構造方法。
2 常用屬性
image:從哪裡載入圖片,值為一個 ImageProvider 物件,ImageProvider 的實現類有 AssetBundleImageProvider(AssetImage 繼承自它)、FileImage、MemoryImage、NetworkImage,需要注意的是,如果選擇 AssetImage 從資源目錄中載入圖片,需在 pubspec.yaml 配置檔案中配置 assets 目錄:
必須是上面的層級關係,但是感覺從資源目錄載入圖片老有問題,有時候顯示不出來但又不報錯,可以試試目錄後面跟上具體檔名,即:
但是這樣每張圖片都得配置,未免太過麻煩,而選擇 NetworkImage 從網路載入圖片就簡單多了,只需要指定圖片的 url 即可。
width 和 heigh:寬和高,不必贅述。
alignment:如果圖片沒有填充滿容器的話,圖片的對齊方式,值為一個 AlignmentGeometry 物件,Alignment 是它的一個實現類,可選值同 Container 的 Alignment 取值一樣。
Alignment.topLeft:垂直靠頂部水平靠左對齊。
Alignment.topCenter:垂直靠頂部水平居中對齊。
Alignment.topRight:垂直靠頂部水平靠右對齊。
Alignment.centerLeft:垂直居中水平靠左對齊。
Alignment.center:垂直和水平居中都對齊。
Alignment.centerRight:垂直居中水平靠右對齊。
Alignment.bottomLeft:垂直靠底部水平靠左對齊。
Alignment.bottomCenter:垂直靠底部水平居中對齊。
Alignment.bottomRight:垂直靠底部水平靠右對齊。
除了上面的常量之外,還可以建立 Alignment 物件指定 x、y 偏移量。
color:在圖片上設定顏色,值為一個 Color 物件,會覆蓋 image 指定的圖片,如果也設定了 colorBlendMode 屬性,則會與 image 混合產生特殊效果。
colorBlendMode:顏色混合模式,類似 BoxDecoration 的 backgroundBlendMode。
excludeFromSemantics:是否啟用影象的語義描述。
filterQuality:影象過濾器的質量級別(使用該屬性還沒看到效果,後面用到了再研究)。
fit:圖片的縮放方式,類似 Android 中 ImageView 的 scaleType,可選值有:
BoxFit.none:將圖片的內容按原大小居中顯示。
BoxFit.contain:將圖片的內容完整居中顯示,通過按比例縮小或原來的 size 使得圖片寬/高等於或小於元件的寬/高,類似 Android 的 centerInside。
BoxFit.cover:按比例放大圖片的 size 居中顯示,類似 Android 的 centerCrop。
BoxFit.fill:把圖片不按比例放大/縮小到元件的大小顯示,類似 Android 的 fitXY。
BoxFit.fitHeight:把圖片的高按照元件的高顯示,寬等比例放大/縮小。
BoxFit.fitWidth:把圖片的寬按照元件的寬顯示,高等比例放大/縮小。
BoxFit.scaleDown:如果圖片寬高大於元件寬高,則讓圖片內容完全居中顯示,此時同 contain,如果圖片寬高小於元件寬高,則按圖片原大小居中顯示,此時同 none。
centerSlice:該屬性用於 .9 圖的中心拉伸,值為一個 Rect 物件,應該就是拉伸區域,我在使用該屬性的時候只有當 fit 設定為 contain 和 fill 時才看到了效果,該屬性應該也是用於圖形變換,不常用。
gaplessPlayback:當 ImageProvider 發生變化後,重新載入圖片的過程中,原圖片的展示是否保留。true 表示保留,false 表示不保留,直接空白等待下一張圖片載入。
matchTextDirection:該屬性值表示圖片的方向是否跟隨文字的方向,其實就相當於左右翻轉,true 表示翻轉,false 表示不翻轉,但是要想該屬性生效,必須使用 Directionality 元件包裹 Image 元件,如下面程式碼:
new Directionality(
textDirection: TextDirection.rtl,
child: new Image(
image: new NetworkImage(imgUrl),
matchTextDirection: true,
),
)
上面程式碼中的 textDirection 屬性值為 TextDirection.rtl,即從右向左,然後 Image 元件的圖片方向跟隨文字方向也是從右向左,即相當於左右翻轉的效果。
repeat:如果圖片沒填充滿容器的話,圖片的重複方式,可選值有:
ImageRepeat.noRepeat:不重複。
ImageRepeat.repeat:X、Y 軸都重複。
ImageRepeat.repeatX:只在 X 軸重複。
ImageRepeat.repeatY:只在 Y 軸重複。
semanticLabel:影象的語義描述,類似 Android 中 ImageView 的 contentDescription 屬性。
下面是一個設定了上面部分屬性的 Image 元件的 demo:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// var imgUrl =
// "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545191828292&di=caef0d773e90142191de9fc5f5871cef&imgtype=0&src=http%3A%2F%2Fimg.mp.sohu.com%2Fq_mini%2Cc_zoom%2Cw_640%2Fupload%2F20170807%2Fb008bbf3df1b490d85e3ff3152ea898e_th.jpg";
var imgUrl =
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545790666&di=45beff1e706ea81d796d2268553c9e6f&imgtype=jpg&er=1&src=http%3A%2F%2Fp1.music.126.net%2FfydScGuKzV4GFdqeCMKhxQ%3D%3D%2F109951163178133629.jpg%3Fparam%3D180y180";
return MaterialApp(
//是否顯示 debug 標籤
debugShowCheckedModeBanner: false,
title: "Image",
home: Scaffold(
appBar: new AppBar(
title: new Text("Image"),
),
body: new Container(
color: new Color(0xFFFF0000),
//子元件
child: new Image(
//從資源目錄中載入圖片,需在 pubspec.yaml 配置檔案中配置 assets 目錄
//flutter:
// assets:
// - assets/images/
//必須是上面的層級關係,但是感覺從資源目錄載入圖片老有問題,有時候顯示不出來但又不報錯,可以試試目錄後面跟上具體檔名,即
//flutter:
// assets:
// - assets/images/iverson.jpg
//但是這樣每張圖片都得配置,未免太過麻煩
// image: new AssetImage("assets/images/iverson.jpg"),
//從網路載入圖片,非常容易,不用配置,而且只要有網就沒什麼問題
image: new NetworkImage(imgUrl),
width: 300,
height: 200,
//如果圖片沒有填充滿容器的話,圖片的對齊方式,值為一個 AlignmentGeometry 物件,Alignment 是它的一個實現類
//可選值同 Container 的 Alignment 取值一樣。
//Alignment.topLeft:垂直靠頂部水平靠左對齊
//Alignment.topCenter:垂直靠頂部水平居中對齊
//Alignment.topRight:垂直靠頂部水平靠右對齊
//Alignment.centerLeft:垂直居中水平靠左對齊
//Alignment.center:垂直和水平居中都對齊
//Alignment.centerRight:垂直居中水平靠右對齊
//Alignment.bottomLeft:垂直靠底部水平靠左對齊
//Alignment.bottomCenter:垂直靠底部水平居中對齊
//Alignment.bottomRight:垂直靠底部水平靠右對齊
//除了上面的常量之外,還可以建立 Alignment 物件指定 x、y 偏移量
alignment: Alignment.center,
//在圖片上設定顏色,值為一個 Color 物件,會覆蓋 image 指定的圖片,如果也設定了 colorBlendMode 屬性,則會與 image 混合產生特殊效果
color: new Color(0xFFFFFF00),
//顏色混合模式,類似 BoxDecoration 的 backgroundBlendMode
colorBlendMode: BlendMode.darken,
// excludeFromSemantics: true,
// filterQuality: FilterQuality.high,
//圖片的縮放方式,類似 Android 中 ImageView 的 scaleType,可選值有:
//BoxFit.none:將圖片的內容按原大小居中顯示。
//BoxFit.contain:將圖片的內容完整居中顯示,通過按比例縮小或原來的 size 使得圖片寬/高等於或小於元件的寬/高,類似 Android 的 centerInside。
//BoxFit.cover:按比例放大圖片的 size 居中顯示,類似 Android 的 centerCrop。
//BoxFit.fill:把圖片不按比例放大/縮小到元件的大小顯示,類似 Android 的 fitXY。
//BoxFit.fitHeight:把圖片的高按照元件的高顯示,寬等比例放大/縮小。
//BoxFit.fitWidth:把圖片的寬按照元件的寬顯示,高等比例放大/縮小。
//BoxFit.scaleDown:如果圖片寬高大於元件寬高,則讓圖片內容完全居中顯示,此時同 contain,如果圖片寬高小於元件寬高,則按圖片原大小居中顯示,此時同 none。
fit: BoxFit.contain,
// centerSlice:new Rect.fromCircle(center: Offset(100.0, 100.0), radius: 10.0),
// gaplessPlayback: true,
matchTextDirection: true,
//如果圖片沒填充滿容器的話,圖片的重複方式,可選值有:
//ImageRepeat.noRepeat:不重複
//ImageRepeat.repeat:X、Y 軸都重複
//ImageRepeat.repeatX:只在 X 軸重複
//ImageRepeat.repeatY:只在 Y 軸重複
repeat: ImageRepeat.noRepeat,
// semanticLabel: "",
),
),
),
);
}
}
執行效果如下:
3 總結
Flutter 載入網路圖片比起 Android 要略微簡單一些,不過要是載入專案包中的圖片可能還需要一些配置,這個可以是利弊皆有,最常用的 Text 和 Image 元件看過後發現其實並不難,還有什麼理由不繼續,加油少年。