如何使用 flutter_svg 解析 SVG 或捕获解析错误

问题描述 投票:0回答:1

我想解析 SVG 字符串来测试它是否是有效的 SVG。这可能吗?

我在错误处理方面遇到了一些困难。 Try/catch 不起作用,RunZonedGuarded 也不起作用。要明白我的意思,请尝试加载无效的 svg 字符串:

try {
    SvgPicture.string('not svg');
}
catch {
   //not catching 
}

下面的方法可以捕获错误而不会使应用程序崩溃,但不是很优雅。令人不快的 android 错误显示在图像框中并溢出。

enter image description here

FutureBuilder<String>(
    future: Future.value(_shopLogoSvg),
    builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
        return SvgPicture.string(snapshot.data!,
                                    fit: BoxFit.contain,
                                    allowDrawingOutsideViewBox: false,);
    } else {
        return const Center(
           child: CircularProgressIndicator()); // or any other loading indicator
    }
  },
);

拥有可用于在加载之前解析不受信任的 SVG 字符串的

SvgPicture.parse
方法将会有所帮助。

或者也许有更好的方法来正确处理错误

flutter_svg

任何帮助表示赞赏!

android flutter svg
1个回答
0
投票

关键是使用

SvgStringLoader
并尝试在调用
loadBytes()
方法时捕获错误,如下所示:

class FooSVG extends StatefulWidget {
  const FooSVG({
    super.key,
    required this.svg,
    this.onError,
  });

  final String svg;
  final Widget Function(dynamic error)? onError;

  @override
  State<FooSVG> createState() => _FooSVGState();
}

class _FooSVGState extends State<FooSVG> {
  Future<SvgStringLoader>? _loaded;

  @override
  void didChangeDependencies() {
    debugPrint('FooSVG.didChangeDependencies');
    super.didChangeDependencies();
    _loaded = _load();
  }

  @override
  void didUpdateWidget(FooSVG oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.svg != widget.svg) {
      debugPrint('FooSVG.didUpdateWidget reload');
      _loaded = _load();
    } else {
      debugPrint('FooSVG.didUpdateWidget no change');
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<SvgStringLoader>(
      future: _loaded,
      builder: (ctx, snapshot) {
        // debugPrint(snapshot.toString());
        return switch (snapshot) {
          (AsyncSnapshot<SvgStringLoader> s) when s.hasData => SvgPicture(s.data!),
          (AsyncSnapshot s) when !s.hasError => const UnconstrainedBox(),
          (AsyncSnapshot s) => _error(s),
        };
      }
    );
  }

  Future<SvgStringLoader> _load() async {
    try {
      final loader = SvgStringLoader(widget.svg);
      await loader.loadBytes(context);
      return loader;
    } catch (e) {
      debugPrint('FooSVG error: $e');
      rethrow;
    }
  }

  Widget _error(AsyncSnapshot snapshot) {
    return widget.onError?.call(snapshot.error!) ?? Text(snapshot.error!.toString());
  }
}

现在用以下方式调用它:

        FooSVG(
          svg: '''
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40">
  <g>
    <g>
      <path d="M4,4h7.59086V6.86658H7.43044V33.13342h4.16042V36H4Z" fill="#727474"/>
      <path d="M28.40914,33.13342h4.159V6.86658h-4.159V4H36V36H28.40914Z" fill="#727474"/>
    </g>
    <path d="M17.61105,13.53573H11V9.01825H29v4.51748H22.39077V32.88H17.61105Z"/>
  </g>
</svg>''',
          onError: (error) {
            return switch (error) {
              XmlParserException(:final message, :final line, :final column) =>
                Text('parser error, $message at [$line:$column]'),
              _ => Text('other error, $error'),
            };
          },
        ),

如果您想检查错误检查,请将

<svg
替换为
<svg,
例如

© www.soinside.com 2019 - 2024. All rights reserved.