更改堆栈中 PlatformViews (iFrame) 的顺序会导致渲染失败

Changing the order of PlatformViews (iFrame) in a Stack causes the render to fail

一个可能的解决方法是避免在 Positioned 小部件 (L: 42) 中使用键,但这会导致 HtmlElementView(或其他显示的项目,如视频)的内部状态重置为实际状态处置。

在下面的示例中,平台工厂的用法可能实现错误,或者密钥不应该这样使用。但是,我怀疑这与 DOM & Flutter 的 SDK 有关。

import 'dart:html' as html;
import 'dart:ui' as ui;
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<int> order = [
    1,
    2,
  ];

  void _reverseOrder() {
    setState(() {
      order = order.reversed.toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Test'),
      ),
      body: Stack(
          children: order
              .map<Widget>((o) => Positioned(
                    key: Key(o.toString() + o.toString()),
                    /*
                    key is used
                    */
                    left: o * 100,
                    top: o * 100,
                    width: o * 250,
                    height: o * 250,
                    child: Stack(
                      children: [
                        child(o),
                        Center(child: Text(o.toString())),
                      ],
                    ),
                  ))
              .toList()),
      floatingActionButton: FloatingActionButton(
        onPressed: _reverseOrder,
        tooltip: 'Reverse order of widgets',
        child: const Icon(Icons.refresh),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Widget child(int id) {
  return createIFrame(
    'sample.pdf',
    id.toString(),
  );

  // // Works without issues with non platform widgets
  // return Container(
  //   color: Color.fromARGB(255, 100 * id, 100 * id, 100 * id),
  // );
}

Widget createIFrame(
  String url,
  String id,
) {
  ui.platformViewRegistry.registerViewFactory(
    id,
    (int viewId) => html.IFrameElement()..src = url,
  );
  return HtmlElementView(viewType: id);
}

有用的链接:

HtmlElementView

platform-views-using-html-slots-web

这实际上是 SDK 中的一个问题。 在引起他们的注意后,它被 flutter 团队修复了。

flutter/issues/101580.