diff --git a/example/lib/main.dart b/example/lib/main.dart index 90a9c46c..432050e3 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -160,77 +160,76 @@ class _MyHomePageState extends State { appBar: new AppBar( title: const Text('Plugin example app'), ), - body: new Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - new Container( - padding: const EdgeInsets.all(24.0), - child: new TextField(controller: _urlCtrl), - ), - new RaisedButton( - onPressed: () { - flutterWebviewPlugin.launch(selectedUrl, - rect: new Rect.fromLTWH( - 0.0, 0.0, MediaQuery.of(context).size.width, 300.0), - userAgent: kAndroidUserAgent); - }, - child: const Text('Open Webview (rect)'), - ), - new RaisedButton( - onPressed: () { - flutterWebviewPlugin.launch(selectedUrl, hidden: true); - }, - child: const Text('Open "hidden" Webview'), - ), - new RaisedButton( - onPressed: () { - flutterWebviewPlugin.launch(selectedUrl); - }, - child: const Text('Open Fullscreen Webview'), - ), - new RaisedButton( - onPressed: () { - Navigator.of(context).pushNamed('/widget'); - }, - child: const Text('Open widget webview'), - ), - new Container( - padding: const EdgeInsets.all(24.0), - child: new TextField(controller: _codeCtrl), - ), - new RaisedButton( - onPressed: () { - final future = - flutterWebviewPlugin.evalJavascript(_codeCtrl.text); - future.then((String result) { - setState(() { - _history.add('eval: $result'); + body: SingleChildScrollView( + child: new Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Container( + padding: const EdgeInsets.all(24.0), + child: new TextField(controller: _urlCtrl), + ), + new RaisedButton( + onPressed: () { + flutterWebviewPlugin.launch(selectedUrl, + rect: new Rect.fromLTWH(0.0, 0.0, MediaQuery.of(context).size.width, 300.0), userAgent: kAndroidUserAgent); + }, + child: const Text('Open Webview (rect)'), + ), + new RaisedButton( + onPressed: () { + flutterWebviewPlugin.launch(selectedUrl, hidden: true); + }, + child: const Text('Open "hidden" Webview'), + ), + new RaisedButton( + onPressed: () { + flutterWebviewPlugin.launch(selectedUrl); + }, + child: const Text('Open Fullscreen Webview'), + ), + new RaisedButton( + onPressed: () { + Navigator.of(context).pushNamed('/widget'); + }, + child: const Text('Open widget webview'), + ), + new Container( + padding: const EdgeInsets.all(24.0), + child: new TextField(controller: _codeCtrl), + ), + new RaisedButton( + onPressed: () { + final future = flutterWebviewPlugin.evalJavascript(_codeCtrl.text); + future.then((String result) { + setState(() { + _history.add('eval: $result'); + }); }); - }); - }, - child: const Text('Eval some javascript'), - ), - new RaisedButton( - onPressed: () { - setState(() { - _history.clear(); - }); - flutterWebviewPlugin.close(); - }, - child: const Text('Close'), - ), - new RaisedButton( - onPressed: () { - flutterWebviewPlugin.getCookies().then((m) { + }, + child: const Text('Eval some javascript'), + ), + new RaisedButton( + onPressed: () { setState(() { - _history.add('cookies: $m'); + _history.clear(); + }); + flutterWebviewPlugin.close(); + }, + child: const Text('Close'), + ), + new RaisedButton( + onPressed: () { + flutterWebviewPlugin.getCookies().then((m) { + setState(() { + _history.add('cookies: $m'); + }); }); - }); - }, - child: const Text('Cookies'), - ), - new Text(_history.join('\n')) - ], + }, + child: const Text('Cookies'), + ), + new Text(_history.join('\n')) + ], + ), ), ); } diff --git a/lib/src/webview_scaffold.dart b/lib/src/webview_scaffold.dart index 06552b51..0c53ed7a 100644 --- a/lib/src/webview_scaffold.dart +++ b/lib/src/webview_scaffold.dart @@ -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'; @@ -60,72 +61,108 @@ class _WebviewScaffoldState extends State { @override void dispose() { super.dispose(); + _resizeTimer?.cancel(); webviewReference.close(); webviewReference.dispose(); } @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); - } 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: 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: const Center( + child: CircularProgressIndicator(), + ), + ), + ); } +} - Rect _buildRect(BuildContext context) { - final fullscreen = widget.appBar == null; +class _WebviewPlaceholder extends SingleChildRenderObjectWidget { + const _WebviewPlaceholder({ + Key key, + @required this.onRectChanged, + Widget child, + }) : super(key: key, child: child); - final mediaQuery = MediaQuery.of(context); - final topPadding = widget.primary ? mediaQuery.padding.top : 0.0; - final top = - fullscreen ? 0.0 : widget.appBar.preferredSize.height + topPadding; + final ValueChanged onRectChanged; - var height = mediaQuery.size.height - top; + @override + RenderObject createRenderObject(BuildContext context) { + return _WebviewPlaceholderRender( + onRectChanged: onRectChanged, + ); + } - if (widget.bottomNavigationBar != null) { - height -= 56.0 + - mediaQuery.padding - .bottom; // todo(lejard_h) find a way to determine bottomNavigationBar programmatically - } + @override + void updateRenderObject(BuildContext context, _WebviewPlaceholderRender renderObject) { + renderObject..onRectChanged = onRectChanged; + } +} - 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; - } +class _WebviewPlaceholderRender extends RenderProxyBox { + ValueChanged _callback; + Rect _rect; + + _WebviewPlaceholderRender({ + RenderBox child, + ValueChanged onRectChanged, + }) : _callback = onRectChanged, + super(child); + + Rect get rect => _rect; + + set onRectChanged(ValueChanged callback) { + if (callback != _callback) { + _callback = callback; + notifyRect(); } + } - if (height < 0.0) { - height = 0.0; + void notifyRect() { + if (_callback != null && _rect != null) { + _callback(_rect); } + } - return new Rect.fromLTWH(0.0, top, mediaQuery.size.width, height); + @override + void paint(PaintingContext context, Offset offset) { + super.paint(context, offset); + final rect = offset & size; + if (_rect != rect) { + _rect = rect; + notifyRect(); + } } }