I managed to put an embedded Youtube video on a web page created using Flutter for Web. The problem is that this video widget disappears while the page is scrolled up or down, and reappears when the scrolling stops. The Chrome developer console shows this error remote.js:34 GET chrome-extension://invalid/ net::ERR_FAILED
Firefox doesn't issue any error message but the flickering of the Youtube video happens there as well. It appears that the webpage continually fetches the Youtube video info again and again during the scroll. How do I fix this?
import 'package:flutter/material.dart';
import 'dart:html' as html;
import 'dart:ui' as ui;
void main() {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'video',
(int viewId) => html.IFrameElement()
..width = '640'
..height = '360'
..src = 'https://www.youtube-nocookie.com/embed/IyFZznAk69U'
..style.border = 'none');
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.purple,
child: Center(
child: Container(
height: 360,
width: 640,
color: Colors.green,
child: HtmlElementView(viewType: "video"),
),
),
),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
Text("test", textDirection: TextDirection.ltr),
],
),
),
);
});
}
}
I believe this is a known issue for Flutter, since the view is being rebuilt it rebuilds the webpage as well. Odd.
If you look at flutter_webview_plugin the author writes:
Warning: The webview is not integrated in the widget tree, it is a native view on top of the flutter view. You won't be able see snackbars, dialogs, or other flutter widgets that would overlap with the region of the screen taken up by the webview.
If you can find a way to get the webview OUT of the widget tree, I bet it works without refreshing, it would of course render over everything else though.
Let me know if you figure out a work around because I'm in the same boat.
We discovered what's the problem with Flutter Web in this case, and wrote a design doc describing the problem and a potential solution.
TL;DR Of The Problem: Certain DOM operations cause certain HTML tags to lose their state (like iframes), causing them to "reload". Flutter uses those operations often when rearranging the render tree of an application, and seems to trigger the issue more often than handcrafted websites. JS-only example.
TL;DR Of The Solution: We need to use the SLOT tag from the Web Components suite, so Flutter doesn't touch the actual contents of the users' HtmlViewElement when the render tree is rearranged. Instead we move around just a SLOT tag. JS-only example.
// Some problematic methods:
target.insertBefore(lastChild, firstChild); // lastChild reloads
target.appendChild(firstChild); // firstChild reloads
// (Maybe other methods cause iframes to reload?)
Early proofs of concept for the fix are showing promise. Anybody can follow the progress of the fix in this Github Issue: flutter/flutter#80524.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With