Flutter图片渐变效果插件image_fade的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter图片渐变效果插件image_fade的使用

ImageFade 是一个用于Flutter的widget,它可以在指定的 image 加载时显示一个 placeholder widget,然后交叉淡入到加载完成的图片。同时它还处理进度和错误情况。当合适时,它会使用 Image.opacity 以提高性能。

如果 image 发生变化,它会在新图片加载完成后淡入到新的图片。将 image 设置为 null 将淡回到占位符。

example image

你可以设置 durationcurve,以及大多数 Image 的属性:widthheightfitalignmentrepeatmatchTextDirectionexcludeFromSemanticssemanticLabel

使用 loadingBuildererrorBuilder 来显示加载进度或错误状态。还可以通过指定 syncDuration 来使用不同的(通常是更快的)持续时间来淡入同步加载的图像、错误或占位符。

示例代码

下面是一个完整的示例demo,展示了如何使用 ImageFade 插件:

import 'package:flutter/material.dart';
import 'package:image_fade/image_fade.dart';

void main() => runApp(const MyApp());

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.yellow,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // Sample images from Wikimedia Commons:
  static const List<String> _imgs = [
    'https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Almeida_Júnior_-_Saudade_%28Longing%29_-_Google_Art_Project.jpg/513px-Almeida_Júnior_-_Saudade_%28Longing%29_-_Google_Art_Project.jpg',
    'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Rafael_-_Retrato_de_um_Cardeal.jpg/786px-Rafael_-_Retrato_de_um_Cardeal.jpg',
    'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/James_McNeill_Whistler_-_La_Princesse_du_pays_de_la_porcelaine_-_brighter.jpg/580px-James_McNeill_Whistler_-_La_Princesse_du_pays_de_la_porcelaine_-_brighter.jpg',
    'https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Hans_Holbein_der_Jüngere_-_Der_Kaufmann_Georg_Gisze_-_Google_Art_Project.jpg/897px-Hans_Holbein_der_Jüngere_-_Der_Kaufmann_Georg_Gisze_-_Google_Art_Project.jpg',
    'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Pieter_Bruegel_the_Elder_-_The_Tower_of_Babel_%28Vienna%29_-_Google_Art_Project_-_edited.jpg/1280px-Pieter_Bruegel_the_Elder_-_The_Tower_of_Babel_%28Vienna%29_-_Google_Art_Project_-_edited.jpg',
  ];

  int _counter = 0;
  bool _clear = true;
  bool _error = false;

  void _incrementCounter() {
    setState(() {
      if (_clear || _error) {
        _clear = _error = false;
      } else {
        _counter = (_counter + 1) % _imgs.length;
      }
    });
  }

  void _clearImage() {
    setState(() {
      _clear = true;
      _error = false;
    });
  }

  void _testError() {
    setState(() => _error = true);
  }

  @override
  Widget build(BuildContext context) {
    String? url;
    if (_error) {
      url = 'error.jpg';
    } else if (!_clear) {
      url = _imgs[_counter];
    }

    String title = _error
        ? 'error'
        : _clear
            ? 'placeholder'
            : 'image #$_counter from Wikimedia';

    return Scaffold(
      appBar: AppBar(title: Text('Showing ' + title)),
      body: Stack(children: <Widget>[
        Positioned.fill(
            child: ImageFade(
          // whenever the image changes, it will be loaded, and then faded in:
          image: url == null ? null : NetworkImage(url),

          // slow-ish fade for loaded images:
          duration: const Duration(milliseconds: 900),

          // if the image is loaded synchronously (ex. from memory), fade in faster:
          syncDuration: const Duration(milliseconds: 150),

          // supports most properties of Image:
          alignment: Alignment.center,
          fit: BoxFit.cover,
          scale: 2,

          // shown behind everything:
          placeholder: Container(
            color: const Color(0xFFCFCDCA),
            alignment: Alignment.center,
            child: const Icon(Icons.photo, color: Colors.white30, size: 128.0),
          ),

          // shows progress while loading an image:
          loadingBuilder: (context, progress, chunkEvent) =>
              Center(child: CircularProgressIndicator(value: progress)),

          // displayed when an error occurs:
          errorBuilder: (context, error) => Container(
            color: const Color(0xFF6F6D6A),
            alignment: Alignment.center,
            child: const Icon(Icons.warning, color: Colors.black26, size: 128.0),
          ),
        ))
      ]),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Next',
            child: const Icon(Icons.navigate_next),
          ),
          const SizedBox(width: 10.0),
          FloatingActionButton(
            onPressed: _clearImage,
            tooltip: 'Clear',
            child: const Icon(Icons.clear),
          ),
          const SizedBox(width: 10.0),
          FloatingActionButton(
            onPressed: _testError,
            tooltip: 'Error',
            child: const Icon(Icons.warning),
          ),
        ],
      ),
    );
  }
}

安装

该插件的已发布版本可以在 pub.dev 上找到。

图片缓存

ImageFade 兼容 CachedNetworkImageProvider

更多信息

更多关于 ImageFade 的信息和示例,请参考其 GitHub仓库


更多关于Flutter图片渐变效果插件image_fade的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图片渐变效果插件image_fade的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用image_fade插件来实现图片渐变效果的代码示例。

首先,确保你已经在pubspec.yaml文件中添加了image_fade依赖项:

dependencies:
  flutter:
    sdk: flutter
  image_fade: ^最新版本号  # 请替换为当前最新版本号

然后,运行flutter pub get来安装依赖项。

以下是一个简单的示例代码,展示了如何使用image_fade插件:

import 'package:flutter/material.dart';
import 'package:image_fade/image_fade.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageFadeExample(),
    );
  }
}

class ImageFadeExample extends StatefulWidget {
  @override
  _ImageFadeExampleState createState() => _ImageFadeExampleState();
}

class _ImageFadeExampleState extends State<ImageFadeExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);

    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOut,
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Image Fade Example'),
      ),
      body: Center(
        child: FadeTransitionImage(
          image: NetworkImage('https://example.com/image1.jpg'), // 替换为你的图片URL
          placeholder: NetworkImage('https://example.com/image2.jpg'), // 替换为你的占位图片URL
          fadeFraction: _animation.value,
        ),
      ),
    );
  }
}

class FadeTransitionImage extends StatelessWidget {
  final ImageProvider image;
  final ImageProvider placeholder;
  final double fadeFraction;

  const FadeTransitionImage({
    Key? key,
    required this.image,
    required this.placeholder,
    required this.fadeFraction,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: <Widget>[
        Opacity(
          opacity: fadeFraction,
          child: Image(
            image: placeholder,
            fit: BoxFit.cover,
          ),
        ),
        Opacity(
          opacity: 1 - fadeFraction,
          child: Image(
            image: image,
            fit: BoxFit.cover,
          ),
        ),
      ],
    );
  }
}

注意:

  1. image_fade插件本身并没有直接提供一个现成的FadeTransitionImage组件,上面的代码实现了一个自定义的FadeTransitionImage组件来模拟渐变效果。
  2. 在上面的代码中,FadeTransitionImage组件通过Opacity组件和Stack组件来实现两张图片的渐变过渡效果。
  3. 使用了AnimationController来控制渐变效果的动画,并设置了一个重复的动画,使得图片在两张图片之间不断渐变。

你可以根据实际需要调整动画的持续时间、曲线以及图片URL等参数。希望这个示例对你有帮助!

回到顶部