Flutter學(xué)習(xí)筆記06-圖片

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??梢宰孕胁殚單臋nImageProvider

1.從asset中加載圖片

在工程根目錄下創(chuàng)建一個(gè)文件夾,并將圖片拷貝到文件夾。在pubspec.yaml中的flutter部分添加如下內(nèi)容:

  assets:
    - assets/images/avatar.png

然后執(zhí)行flutter pub get。
ps:yaml文件對(duì)縮進(jìn)嚴(yán)格,所以必須嚴(yán)格按照每一層兩個(gè)空格的方式進(jìn)行縮進(jìn),此處assets前面應(yīng)有兩個(gè)空格。筆者習(xí)慣創(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è)快捷的構(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,
    );
  }
}

運(yùn)行上面兩個(gè)示例,效果圖如下:

如果加載時(shí)報(bào)錯(cuò)找不到圖片資源,有可能是兩個(gè)原因:
1.pubspec.yaml中書寫不規(guī)范。不規(guī)范的縮進(jìn)和字符都可能導(dǎo)致配置的內(nèi)容不生效。要注意yaml的一個(gè)縮進(jìn)是2個(gè)空格。如下圖所示:

asset配置

2.代碼中的圖片相對(duì)路徑要和工程中實(shí)際路徑不一致。例如:項(xiàng)目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è)快捷的構(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,
    );
  }
}

代碼運(yùn)行效果圖如下:

3.參數(shù)

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

const Image({
  ...
  this.width, // 圖片的寬
  this.height, // 圖片高度
  this.color, // 圖片的混合色值
  this.colorBlendMode, // 混合模式
  this.fit,// 縮放模式
  this.alignment = Alignment.center, // 對(duì)齊方式
  this.repeat = ImageRepeat.noRepeat, // 重復(fù)方式
  ...
})
  • width height
    用于設(shè)置圖片的寬、高,當(dāng)不指定寬高時(shí),圖片會(huì)根據(jù)當(dāng)前父容器的限制,盡可能的顯示其原始大小,如果只設(shè)置width、height的其中一個(gè),那么另一個(gè)屬性默認(rèn)會(huì)按比例縮放,可以通過fit屬性來指定適應(yīng)規(guī)則。
  • fit
    該屬性用于在圖片的顯示空間和圖片本身大小不同時(shí)指定圖片的適應(yīng)模式。適應(yīng)模式是在BoxFit中定義,它是一個(gè)枚舉類型,有如下值:
    fill:會(huì)拉伸填充滿顯示空間,圖片本身長寬比會(huì)發(fā)生變化,圖片會(huì)變形。
    cover:會(huì)按圖片的長寬比放大后居中填滿顯示空間,圖片不會(huì)變形,超出顯示空間部分會(huì)被剪裁。
    contain:圖片的默認(rèn)適應(yīng)規(guī)則,圖片會(huì)在保證圖片本身長寬比不變的情況下縮放以適應(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值,代碼示例如下:
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(),
      ),
    );
  }
}

代碼運(yùn)行效果圖如下:
  • color colorBlendMode
    在圖片繪制時(shí)可以對(duì)每一個(gè)像素進(jìn)行顏色混合處理,color指定混合色,colorBlendMode指定混合模式,代碼示例:
Image.asset(
  'assets/images/avatar.png',
  width: 100,
  color: Colors.blue,
  colorBlendMode: BlendMode.difference,
),

運(yùn)行效果如下:
  • repeat
    當(dāng)圖片本身大小小于顯示空間時(shí),指定圖片的重復(fù)規(guī)則。代碼示例如下:
Image.asset(
  'assets/images/avatar.png',
  width: 100,
  height: 200,
  repeat: ImageRepeat.repeatY,
),

代碼運(yùn)行效果圖如下:

4.實(shí)現(xiàn)圓角圖像

實(shí)現(xiàn)圓角圖像有多種方式。

  • CircleAvatar
    CircleAvatar可以實(shí)現(xiàn)圓角頭像,也可以添加一個(gè)子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('貓頭鷹'),
      ),
    );
  }
}

運(yùn)行效果圖如下:
  • ClipOval
    ClipOval也可以實(shí)現(xiàn)圓角頭像,通常是在只有頭像時(shí)使用。代碼示例如下:
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,
      ),
    );
  }
}

運(yùn)行效果圖如下:
  • ClipRRect
    ClipRRect用于實(shí)現(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,
      ),
    );
  }
}

運(yùn)行效果圖如下:

5.加載網(wǎng)絡(luò)圖片時(shí)顯示占位圖

加載網(wǎng)絡(luò)圖片時(shí)顯示占位圖可以用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
    默認(rèn)顯示的占位圖
  • image
    真正顯示的圖片
  • fadeOutDuration fadeOutDuration
    placeholder消失image顯示的過程有一個(gè)淡進(jìn)淡出,fadeOutDuration和fadeOutDuration就是設(shè)置淡進(jìn)淡出的時(shí)間,不想那個(gè)要這種效果將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,
      ),
    );
  }
}

但是這種方法沒有緩存每次都需要一段時(shí)間加載網(wǎng)絡(luò)圖片,cached_network_image 這個(gè)庫實(shí)現(xiàn)了圖片緩存加載和占位圖效果,可自行查閱文檔。

代碼傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容