Skip to content

Commit

Permalink
Merge pull request #178 from slightfoot/master
Browse files Browse the repository at this point in the history
Fix rect capture on WebviewScaffold
  • Loading branch information
slightfoot authored Nov 14, 2018
2 parents fc48ca7 + 0e7cf13 commit ec3de70
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 119 deletions.
135 changes: 67 additions & 68 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -160,77 +160,76 @@ class _MyHomePageState extends State<MyHomePage> {
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'))
],
),
),
);
}
Expand Down
139 changes: 88 additions & 51 deletions lib/src/webview_scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -60,72 +61,108 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
@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<Rect> 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<Rect> _callback;
Rect _rect;

_WebviewPlaceholderRender({
RenderBox child,
ValueChanged<Rect> onRectChanged,
}) : _callback = onRectChanged,
super(child);

Rect get rect => _rect;

set onRectChanged(ValueChanged<Rect> 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();
}
}
}

0 comments on commit ec3de70

Please sign in to comment.