【问题标题】:How to convert icon widget to ImageProvider如何将图标小部件转换为 ImageProvider
【发布时间】:2020-09-07 14:49:36
【问题描述】:

我想在我的程序中使用 Flutter 的 Material design 图标,为此,我需要使用 Icon 小部件。我有一个网络图像(NetworkImage 小部件),如果 URL 为空,我想显示 Material design 图标。

Container(
      width: 48.0,
      height: 48.0,
      decoration: BoxDecoration(
          image: DecorationImage(
            image: imgLink.isEmpty
                ? Icon(Icons.person_outline)
                : NetworkImage(
                    imgLink,
                  ),
          ),
          borderRadius: BorderRadius.circular(10.0)),
    ),

它显示错误,因为图标不是 ImageProvider 的子类型。现在我如何将 Icon 转换为 ImageProvider 或任何其他方式。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    解决方案是创建自己的转换图标的提供程序:

    import 'dart:ui' as ui;
    
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
    class IconImageProvider extends ImageProvider<IconImageProvider> {
      final IconData icon;
      final double scale;
      final int size;
      final Color color;
    
      IconImageProvider(this.icon, {this.scale = 1.0, this.size = 48, this.color = Colors.white});
    
      @override
      Future<IconImageProvider> obtainKey(ImageConfiguration configuration) => SynchronousFuture<IconImageProvider>(this);
    
      @override
      ImageStreamCompleter load(IconImageProvider key, DecoderCallback decode) => OneFrameImageStreamCompleter(_loadAsync(key));
    
      Future<ImageInfo> _loadAsync(IconImageProvider key) async {
        assert(key == this);
    
        final recorder = ui.PictureRecorder();
        final canvas = Canvas(recorder);
        canvas.scale(scale, scale);
        final textPainter = TextPainter(textDirection: TextDirection.rtl);
        textPainter.text = TextSpan(
          text: String.fromCharCode(icon.codePoint),
          style: TextStyle(
            fontSize: size.toDouble(),
            fontFamily: icon.fontFamily,
            color: color,
          ),
        );
        textPainter.layout();
        textPainter.paint(canvas, Offset.zero);
        final image = await recorder.endRecording().toImage(size, size);
        return ImageInfo(image: image, scale: key.scale);
      }
    
      @override
      bool operator ==(dynamic other) {
        if (other.runtimeType != runtimeType) return false;
        final IconImageProvider typedOther = other;
        return icon == typedOther.icon && scale == typedOther.scale && size == typedOther.size && color == typedOther.color;
      }
    
      @override
      int get hashCode => hashValues(icon.hashCode, scale, size, color);
    
      @override
      String toString() => '$runtimeType(${describeIdentity(icon)}, scale: $scale, size: $size, color: $color)';
    }
    

    这是一个标准的ImageProvider,所有的股票看起来都像这样。实际转换在_loadAsync() 内。相当简单,只是一个普通的Canvas 操作将图标绘制为文本(实际上它文本)。

    【讨论】:

    • 由于某种原因,上面的代码在使用 CupertinoIcons 时会失败。我只是得到里面有 X 的小方块来表示(我猜)没有找到这个字体的代码点。有什么想法吗??
    【解决方案2】:

    BoxDecorationContainer 中的图像仅支持 ImageProvider 类具有 以下实施者 AssetBundleImageProviderFileImageMemoryImageNetworkImageResizeImageScrollAwareImageProvider 所以它不支持图标小部件,因为图标小部件有自己的 IconData 类所以这就是为什么颤振给你错误, “图标不是 ImageProvider 的子类型”。

    【讨论】:

      猜你喜欢
      • 2020-12-08
      • 1970-01-01
      • 2022-07-30
      • 1970-01-01
      • 2019-08-24
      • 2011-10-14
      • 2022-08-15
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多