瀏覽代碼

Fix rect capture on WebviewScaffold

Simon Lightfoot 7 年之前
父節點
當前提交
0e7cf1351b
共有 2 個文件被更改,包括 155 次插入119 次删除
  1. 67 68
      example/lib/main.dart
  2. 88 51
      lib/src/webview_scaffold.dart

+ 67 - 68
example/lib/main.dart

@@ -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'))
+          ],
+        ),
       ),
     );
   }

+ 88 - 51
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<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();
+    }
   }
 }