flutter中图片的缓存,本地,远程,Icon,placeholder

823 阅读3分钟

1. Image

Flutter 中的图片控件是Image ,支持下面几种类型的构造函数:

  • Image 从ImageProvider获取图片
  • Image.asset 使用key从AssetBundle获取图片
  • Image.network 从网络获取图片
  • Image.file 本地文件获取图片
  • Image.memory 从Uint8List获取图片

支持的图片类型:JPEG, PNG, GIF, Animated GIF, WebP, Animated WebP, BMP, WBMP

2.加载网络图片

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
​
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Image.network('http://www.devio.org/img/avatar.png'),
    );
  }
}

3.加载静态图片

在 pubspec.yaml 文件中声明图片资源路径;

使用 AssetImage 加载该图片;

首先把图片放到指定目录下面,assets文件夹要在根目录下:

1.png 然后在 pubspec.yaml 文件中指定目录:

flutter:
  uses-material-design: true
  assets:
    - assets/images/my_icon.jpg

最后代码中添加:

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
​
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Image(height: 100,width: 100,
        image: AssetImage('assets/images/my_icon.jpg'),),
    );
  }
}

另一种方法通过 Image.asset 加载

home: Image.asset('assets/images/my_icon.jpg',width: 100,height: 100)

4.加载本地图片

加载手机中的图片

Image.file(File('/storage/emulated/0/Download/test.jpg'),width: 100,height: 100)

加载手机中的图片,有一些别的问题,添加权限获取授权,然后再进行显示图片,这里代码较多,所以写到另一篇文章中,下面链接文章最后有完整代码:

blog.csdn.net/wuqingsen1/…

5.设置 Placeholder

transparent_image 插件加载图片,可以显示进度条,逐渐透明显示出来加载的图片:

pubspec.yaml 添加:

transparent_image: ^2.0.0

添加包:

import 'package:transparent_image/transparent_image.dart';

添加代码:

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
​
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Stack(
        children: [
          //进度条
          Center(child: CircularProgressIndicator(),),
          Center(
            //网络加载时渐变出现
            child: FadeInImage.memoryNetwork(
              // Placeholder
              placeholder: kTransparentImage,
              image: "https://www.devio.org/img/avatar.png",
            ),
          )
        ],
      ),
    );
  }
}

加载本地资源图片,先显示我们的gif进度条,然后再显示加载成功的图片:

 @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Stack(
        children: [
          // 进度条
          Center(
            // 网络加载时渐变出现
            child: FadeInImage.assetNetwork(
              // Placeholder
              placeholder: 'assets/images/my_icon.gif',
              image: "https://www.devio.org/img/avatar.png",
            ),
          )
        ],
      ),
    );
  }

extra: blurhash模糊placeholder

利用flutter_blurhash 插件模糊图片:

pubspec.yaml 添加:

flutter_blurhash: ^0.7.0

添加包:

import 'package:flutter_blurhash/flutter_blurhash.dart';

添加代码:

class BlurHashApp extends StatelessWidget {
  const BlurHashApp({Key? key}) : super(key: key);
​
  @override
  Widget build(BuildContext context) => MaterialApp(
    home: Scaffold(
      appBar: AppBar(title: const Text("BlurHash")),
      body: const SizedBox.expand(
        child: Center(
          child: AspectRatio(
            aspectRatio: 1.6,
            child: BlurHash(hash: "L5H2EC=PM+yV0g-mq.wG9c010J}I"),
          ),
        ),
      ),
    ),
  );
}

具体的blurhash值可通过网站blurha.sh/获取

image-20220513163829729.png

6.配置图片缓存

利用cached_network_image 插件加载网络图片,缓存到本地:

pubspec.yaml 添加:

cached_network_image: ^3.2.0

添加包:

import 'package:cached_network_image/cached_network_image.dart'; 添加代码:

  home: Scaffold(
      appBar: AppBar(
        title: Text('title'),
      ),
      body: Center(
        child: CachedNetworkImage(
          // Placeholder
          placeholder: (context, url) => CircularProgressIndicator(),
          imageUrl: "https://www.devio.org/img/avatar.png",
          errorWidget: (context, url, error) => new Icon(Icons.error),
        ),
      ),
  )

官方实例:

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:baseflow_plugin_template/baseflow_plugin_template.dart';
import 'package:flutter_blurhash/flutter_blurhash.dart';
​
void main() {
  CachedNetworkImage.logLevel = CacheManagerLogLevel.debug;
​
  runApp(BaseflowPluginExample(
    pluginName: 'CachedNetworkImage',
    githubURL: 'https://github.com/Baseflow/flutter_cache_manager',
    pubDevURL: 'https://pub.flutter-io.cn/packages/flutter_cache_manager',
    pages: [
      BasicContent.createPage(),
      ListContent.createPage(),
      GridContent.createPage(),
    ],
  ));
}
​
/// Demonstrates a [StatelessWidget] containing [CachedNetworkImage]
class BasicContent extends StatelessWidget {
  const BasicContent({Key? key}) : super(key: key);
​
  static ExamplePage createPage() {
    return ExamplePage(Icons.image, (context) => const BasicContent());
  }
​
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _blurHashImage(),
            _sizedContainer(
              const Image(
                image: CachedNetworkImageProvider(
                  'https://via.placeholder.com/350x150',
                ),
              ),
            ),
            _sizedContainer(
              CachedNetworkImage(
                progressIndicatorBuilder: (context, url, progress) => Center(
                  child: CircularProgressIndicator(
                    value: progress.progress,
                  ),
                ),
                imageUrl:
                'https://images.unsplash.com/photo-1532264523420-881a47db012d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9',
              ),
            ),
            _sizedContainer(
              CachedNetworkImage(
                placeholder: (context, url) =>
                const CircularProgressIndicator(),
                imageUrl: 'https://via.placeholder.com/200x150',
              ),
            ),
            _sizedContainer(
              CachedNetworkImage(
                imageUrl: 'https://via.placeholder.com/300x150',
                imageBuilder: (context, imageProvider) => Container(
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.cover,
                      colorFilter: const ColorFilter.mode(
                        Colors.red,
                        BlendMode.colorBurn,
                      ),
                    ),
                  ),
                ),
                placeholder: (context, url) =>
                const CircularProgressIndicator(),
                errorWidget: (context, url, error) => const Icon(Icons.error),
              ),
            ),
            CachedNetworkImage(
              imageUrl: 'https://via.placeholder.com/300x300',
              placeholder: (context, url) => const CircleAvatar(
                backgroundColor: Colors.amber,
                radius: 150,
              ),
              imageBuilder: (context, image) => CircleAvatar(
                backgroundImage: image,
                radius: 150,
              ),
            ),
            _sizedContainer(
              CachedNetworkImage(
                imageUrl: 'https://notAvalid.uri',
                placeholder: (context, url) =>
                const CircularProgressIndicator(),
                errorWidget: (context, url, error) => const Icon(Icons.error),
              ),
            ),
            _sizedContainer(
              CachedNetworkImage(
                imageUrl: 'not a uri at all',
                placeholder: (context, url) =>
                const CircularProgressIndicator(),
                errorWidget: (context, url, error) => const Icon(Icons.error),
              ),
            ),
            _sizedContainer(
              CachedNetworkImage(
                maxHeightDiskCache: 10,
                imageUrl: 'https://via.placeholder.com/350x200',
                placeholder: (context, url) =>
                const CircularProgressIndicator(),
                errorWidget: (context, url, error) => const Icon(Icons.error),
                fadeOutDuration: const Duration(seconds: 1),
                fadeInDuration: const Duration(seconds: 3),
              ),
            ),
          ],
        ),
      ),
    );
  }
​
  Widget _blurHashImage() {
    return SizedBox(
      width: double.infinity,
      child: CachedNetworkImage(
        placeholder: (context, url) => const AspectRatio(
          aspectRatio: 1.6,
          child: BlurHash(hash: 'LEHV6nWB2yk8pyo0adR*.7kCMdnj'),
        ),
        imageUrl: 'https://blurha.sh/assets/images/img1.jpg',
        fit: BoxFit.cover,
      ),
    );
  }
​
  Widget _sizedContainer(Widget child) {
    return SizedBox(
      width: 300.0,
      height: 150.0,
      child: Center(child: child),
    );
  }
}
​
/// Demonstrates a [ListView] containing [CachedNetworkImage]
class ListContent extends StatelessWidget {
  const ListContent({Key? key}) : super(key: key);
​
  static ExamplePage createPage() {
    return ExamplePage(Icons.list, (context) => const ListContent());
  }
​
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: (BuildContext context, int index) => Card(
        child: Column(
          children: <Widget>[
            CachedNetworkImage(
              imageUrl: 'https://loremflickr.com/320/240/music?lock=$index',
              placeholder: (BuildContext context, String url) => Container(
                width: 320,
                height: 240,
                color: Colors.purple,
              ),
            ),
          ],
        ),
      ),
      itemCount: 250,
    );
  }
}
​
/// Demonstrates a [GridView] containing [CachedNetworkImage]
class GridContent extends StatelessWidget {
  const GridContent({Key? key}) : super(key: key);
​
  static ExamplePage createPage() {
    return ExamplePage(Icons.grid_on, (context) => const GridContent());
  }
​
  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      itemCount: 250,
      gridDelegate:
      const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
      itemBuilder: (BuildContext context, int index) => CachedNetworkImage(
        imageUrl: 'https://loremflickr.com/100/100/music?lock=$index',
        placeholder: _loader,
        errorWidget: _error,
      ),
    );
  }
​
  Widget _loader(BuildContext context, String url) {
    return const Center(
      child: CircularProgressIndicator(),
    );
  }
​
  Widget _error(BuildContext context, String url, dynamic error) {
    return const Center(child: Icon(Icons.error));
  }
}

7.加载 Icon

使用 Flutter 内置的 material_fonts :

 @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('title'),
        ),
        body: Center(
          child: new Icon(Icons.android,size:100),
        ),
      ),
    );
  }

\