|
|
@@ -2,6 +2,7 @@ import 'dart:async';
|
|
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
import 'package:flutter/material.dart';
|
|
|
+import 'package:flutter/rendering.dart';
|
|
|
|
|
|
import 'base.dart';
|
|
|
|
|
|
@@ -73,6 +74,7 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
|
|
|
@override
|
|
|
void dispose() {
|
|
|
super.dispose();
|
|
|
+ _resizeTimer?.cancel();
|
|
|
webviewReference.close();
|
|
|
if (widget.hidden) {
|
|
|
_onStateChanged.cancel();
|
|
|
@@ -82,64 +84,99 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
|
|
|
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
- if (_rect == null) {
|
|
|
- _rect = _buildRect(context);
|
|
|
- webviewReference.launch(widget.url,
|
|
|
- headers: widget.headers,
|
|
|
- withJavascript: widget.withJavascript,
|
|
|
- clearCache: widget.clearCache,
|
|
|
- clearCookies: widget.clearCookies,
|
|
|
- enableAppScheme: widget.enableAppScheme,
|
|
|
- userAgent: widget.userAgent,
|
|
|
- rect: _rect,
|
|
|
- withZoom: widget.withZoom,
|
|
|
- withLocalStorage: widget.withLocalStorage,
|
|
|
- withLocalUrl: widget.withLocalUrl,
|
|
|
- scrollBar: widget.scrollBar,
|
|
|
- hidden: widget.hidden);
|
|
|
- } else {
|
|
|
- final rect = _buildRect(context);
|
|
|
- if (_rect != rect) {
|
|
|
- _rect = rect;
|
|
|
- _resizeTimer?.cancel();
|
|
|
- _resizeTimer = new Timer(new Duration(milliseconds: 300), () {
|
|
|
- // avoid resizing to fast when build is called multiple time
|
|
|
- webviewReference.resize(_rect);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- return new Scaffold(
|
|
|
- appBar: widget.appBar,
|
|
|
- persistentFooterButtons: widget.persistentFooterButtons,
|
|
|
- bottomNavigationBar: widget.bottomNavigationBar,
|
|
|
- body: widget.initialChild ?? const Center(child: const CircularProgressIndicator()));
|
|
|
+ return Scaffold(
|
|
|
+ appBar: widget.appBar,
|
|
|
+ persistentFooterButtons: widget.persistentFooterButtons,
|
|
|
+ bottomNavigationBar: widget.bottomNavigationBar,
|
|
|
+ body: _WebviewPlaceholder(
|
|
|
+ onRectChanged: (Rect value) {
|
|
|
+ if (_rect == null) {
|
|
|
+ _rect = value;
|
|
|
+ webviewReference.launch(
|
|
|
+ widget.url,
|
|
|
+ headers: widget.headers,
|
|
|
+ withJavascript: widget.withJavascript,
|
|
|
+ clearCache: widget.clearCache,
|
|
|
+ clearCookies: widget.clearCookies,
|
|
|
+ enableAppScheme: widget.enableAppScheme,
|
|
|
+ userAgent: widget.userAgent,
|
|
|
+ rect: _rect,
|
|
|
+ withZoom: widget.withZoom,
|
|
|
+ withLocalStorage: widget.withLocalStorage,
|
|
|
+ withLocalUrl: widget.withLocalUrl,
|
|
|
+ scrollBar: widget.scrollBar,
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ if (_rect != value) {
|
|
|
+ _rect = value;
|
|
|
+ _resizeTimer?.cancel();
|
|
|
+ _resizeTimer = Timer(const Duration(milliseconds: 250), () {
|
|
|
+ // avoid resizing to fast when build is called multiple time
|
|
|
+ webviewReference.resize(_rect);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ child: widget.initialChild ?? const Center(child: const CircularProgressIndicator()),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class _WebviewPlaceholder extends SingleChildRenderObjectWidget {
|
|
|
+ const _WebviewPlaceholder({
|
|
|
+ Key key,
|
|
|
+ @required this.onRectChanged,
|
|
|
+ Widget child,
|
|
|
+ }) : super(key: key, child: child);
|
|
|
+
|
|
|
+ final ValueChanged<Rect> onRectChanged;
|
|
|
+
|
|
|
+ @override
|
|
|
+ RenderObject createRenderObject(BuildContext context) {
|
|
|
+ return _WebviewPlaceholderRender(
|
|
|
+ onRectChanged: onRectChanged,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ void updateRenderObject(BuildContext context, _WebviewPlaceholderRender renderObject) {
|
|
|
+ renderObject..onRectChanged = onRectChanged;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- Rect _buildRect(BuildContext context) {
|
|
|
- final fullscreen = widget.appBar == null;
|
|
|
+class _WebviewPlaceholderRender extends RenderProxyBox {
|
|
|
+ ValueChanged<Rect> _callback;
|
|
|
+ Rect _rect;
|
|
|
|
|
|
- final mediaQuery = MediaQuery.of(context);
|
|
|
- final topPadding = widget.primary ? mediaQuery.padding.top : 0.0;
|
|
|
- final top = fullscreen ? 0.0 : widget.appBar.preferredSize.height + topPadding;
|
|
|
+ _WebviewPlaceholderRender({
|
|
|
+ RenderBox child,
|
|
|
+ ValueChanged<Rect> onRectChanged,
|
|
|
+ }) : _callback = onRectChanged,
|
|
|
+ super(child);
|
|
|
|
|
|
- var height = mediaQuery.size.height - top;
|
|
|
+ Rect get rect => _rect;
|
|
|
|
|
|
- if (widget.bottomNavigationBar != null) {
|
|
|
- height -= 56.0 +
|
|
|
- mediaQuery.padding.bottom; // todo(lejard_h) find a way to determine bottomNavigationBar programmatically
|
|
|
+ set onRectChanged(ValueChanged<Rect> callback) {
|
|
|
+ if (callback != _callback) {
|
|
|
+ _callback = callback;
|
|
|
+ notifyRect();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (widget.persistentFooterButtons != null) {
|
|
|
- height -= 53.0; // todo(lejard_h) find a way to determine persistentFooterButtons programmatically
|
|
|
- if (widget.bottomNavigationBar == null) {
|
|
|
- height -= mediaQuery.padding.bottom;
|
|
|
- }
|
|
|
+ void notifyRect() {
|
|
|
+ if (_callback != null && _rect != null) {
|
|
|
+ _callback(_rect);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (height < 0.0) {
|
|
|
- height = 0.0;
|
|
|
+ @override
|
|
|
+ void paint(PaintingContext context, Offset offset) {
|
|
|
+ super.paint(context, offset);
|
|
|
+ final rect = offset & size;
|
|
|
+ if (_rect != rect) {
|
|
|
+ _rect = rect;
|
|
|
+ notifyRect();
|
|
|
}
|
|
|
-
|
|
|
- return new Rect.fromLTWH(0.0, top, mediaQuery.size.width, height);
|
|
|
}
|
|
|
}
|