如何检查图像资产是不是存在,然后将其用作圆形头像或在圆形头像中写下姓名的第一个字母

Posted

技术标签:

【中文标题】如何检查图像资产是不是存在,然后将其用作圆形头像或在圆形头像中写下姓名的第一个字母【英文标题】:How to check if image assets exist then use it as circle avatar or write first letter of name in circle avatar如何检查图像资产是否存在,然后将其用作圆形头像或在圆形头像中写下姓名的第一个字母 【发布时间】:2021-10-07 05:35:35 【问题描述】:

我的资产文件夹中有一些图像。我只想检查用户输入的名称是否与图像匹配。如果匹配,那么我想在圆形头像中使用该图像,或者在圆形头像中使用名称的第一个字母。

我的逻辑

我正在尝试通过rootBundle.loadString() 加载图像。如果图像或路径不存在,则会抛出异常。这就是我知道我需要使用名称的第一个字母的方式。

到目前为止我已经尝试过什么

我的第一种方法只是检查路径是否存在。为此,我使用了以下说明。但它给我的总是假的。我找不到合适的理由。

io.File(syncPath).exists();

因此,我使用rootBundle.loadString() 来捕获异常。

我在互联网上搜索过,但我找不到与我的问题相关的解决方案(可能是因为我的搜索技巧不好)

我也尝试过以下解决方案, 我尝试将FutureBuilder 包装在Card() 上,例如

  child: FutureBuilder<String>(
    future: rootBundle.loadString(imagePath),
    builder: (BuildContext context,snapshot) 
           if (snapshot.hasData)
           return Card(...)// card and avatar with image
          else 
         return Card(...)// card and avatar with first letter of name
        

但是,我还是抓不到异常。

这是我的代码。

class ItemCardListTile extends StatefulWidget 
  final bool tobuy;
  final String name;
  const ItemCardListTile(
    Key? key,
    required this.tobuy,
    required this.name,
  ) : super(key: key);

  @override
  _ItemCardListTileState createState() => _ItemCardListTileState();


class _ItemCardListTileState extends State<ItemCardListTile> 
  final log = logger(ItemCardListTile);

  String assetsPath = 'assets/images/';

  String imageExt = '.png';

  @override
  void initState() 
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    final String firstLettter = widget.name[0];
    AssetImage? imageAssets;
    String imagePath = '$assetsPath$widget.name.toLowerCase()$imageExt';

    Future<AssetImage?> checkImageExist(String imagePath) async 
      try 
        await rootBundle.loadString(imagePath);
        imageAssets = AssetImage(imagePath);
       catch (e) 
        print(e.toString());
        return null;
      
    

    return Card(
      child: widget.tobuy
          ? ListTile(
              leading: (checkImageExist(imagePath) == null)
                  ? CircleAvatar(
                      // backgroundImage: imageAssets,
                      child: Text(firstLettter),
                    )
                  : CircleAvatar(backgroundImage: imageAssets),
              title: Text(widget.name),
            )
          : const SizedBox(),
    );
  

请帮我解决我的问题。 非常感谢您。

根据@PeterKoltai 的评论更新了我的代码 现在我得到 FormatException: Unexpected extension byte (at offset 0) 。我的图像路径是正确的。我可以使用 AssestImage() 显示圆形头像。

 Widget build(BuildContext context) 
    final String firstLettter = widget.name[0];
    final String _imagePath = 'assets/images/broccoli.png';

    Future checkImageExist(String imagePath) async 
      try 
        return await rootBundle.loadString(imagePath);
       catch (e) 
        print(e.toString());
        return null;
      
    

    return FutureBuilder(
      future: checkImageExist(_imagePath),
      builder: (BuildContext context, snapshot) 
        if (snapshot.hasError != null) 
          return Card(
            child: widget.tobuy
                ? ListTile(
                    leading:CircleAvatar(
                      child: Text(firstLettter),
                    ),
                    title: Text(widget.name),
                  )
                : const SizedBox(),
          );
         else
          return Container();
      ,
    );
  

【问题讨论】:

您是否使用snapshot.data 使用列表正确获取名称? 这对您有帮助吗:***.com/questions/50685492/check-if-asset-exists? 不,我只是想捕获一个异常。以便我知道该图像不存在。 @PeterKoltai 从这个链接我发现这个“等待 rootBundle .loadString('path/to/file.json');”但不知何故我无法捕捉到所有的异常。 谢谢,@enzo。我已经通过使用rootBundle.load() 解决了这个问题 【参考方案1】:

所以最后大家帮我解决了这个问题。现在我可以捕捉到所有的错误。 这是我的最终代码。

class ItemCardListTile extends StatelessWidget 
  final bool tobuy;
  final String name;
  ItemCardListTile(
    Key? key,
    required this.tobuy,
    required this.name,
  ) : super(key: key);

  final log = logger(ItemCardListTile);
  String assetsPath = 'assets/images/';
  String imageExt = '.png';

  @override
  Widget build(BuildContext context) 
    final String firstLettter = name[0];
    final String imagePath = '$assetsPath$name.toLowerCase()$imageExt';
    Future<AssetImage?> checkImageExist(String imagePath) async 
      try 
        await rootBundle.load(imagePath); //  return always null so
        return AssetImage(imagePath); // I have added AssetImage
       catch (e) 
        print(e.toString());
        return null;
      
    

    return FutureBuilder(
      future: checkImageExist(imagePath),
      builder: (BuildContext context, snapshot) 
        return Card(
          child: tobuy
              ? ListTile(
                  leading: CircleAvatar(
                    // here I am checking if image is available then I use it otherwise I write
                    // first letter of the name
                    foregroundImage:
                        (snapshot.data != null) ? AssetImage(imagePath) : null,
                    child: Text(firstLettter),
                  ),
                  title: Text(name),
                )
              : const SizedBox(),
        );
      ,
    );
  

【讨论】:

以上是关于如何检查图像资产是不是存在,然后将其用作圆形头像或在圆形头像中写下姓名的第一个字母的主要内容,如果未能解决你的问题,请参考以下文章

iOS 裁剪圆形图像并显示(类似于微信头像)

可动态显示圆形图像或圆形文字的AvatarImageView

如何在 Julia 语言中绘制圆形扇区?

Docker图像保存如何在加载前检查是不是存在?

如何选择一张图片来设置头像

Flutter 网络图像不适合圆形头像