webview_scaffold.dart 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import 'dart:async';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/rendering.dart';
  5. import 'base.dart';
  6. class WebviewScaffold extends StatefulWidget {
  7. final PreferredSizeWidget appBar;
  8. final String url;
  9. final bool withJavascript;
  10. final bool clearCache;
  11. final bool clearCookies;
  12. final bool enableAppScheme;
  13. final String userAgent;
  14. final bool primary;
  15. final List<Widget> persistentFooterButtons;
  16. final Widget bottomNavigationBar;
  17. final bool withZoom;
  18. final bool withLocalStorage;
  19. final bool withLocalUrl;
  20. final bool scrollBar;
  21. final Map<String, String> headers;
  22. const WebviewScaffold(
  23. {Key key,
  24. this.appBar,
  25. @required this.url,
  26. this.headers,
  27. this.withJavascript,
  28. this.clearCache,
  29. this.clearCookies,
  30. this.enableAppScheme,
  31. this.userAgent,
  32. this.primary = true,
  33. this.persistentFooterButtons,
  34. this.bottomNavigationBar,
  35. this.withZoom,
  36. this.withLocalStorage,
  37. this.withLocalUrl,
  38. this.scrollBar})
  39. : super(key: key);
  40. @override
  41. _WebviewScaffoldState createState() => new _WebviewScaffoldState();
  42. }
  43. class _WebviewScaffoldState extends State<WebviewScaffold> {
  44. final webviewReference = new FlutterWebviewPlugin();
  45. Rect _rect;
  46. Timer _resizeTimer;
  47. @override
  48. void initState() {
  49. super.initState();
  50. webviewReference.close();
  51. }
  52. @override
  53. void dispose() {
  54. super.dispose();
  55. _resizeTimer?.cancel();
  56. webviewReference.close();
  57. webviewReference.dispose();
  58. }
  59. @override
  60. Widget build(BuildContext context) {
  61. return Scaffold(
  62. appBar: widget.appBar,
  63. persistentFooterButtons: widget.persistentFooterButtons,
  64. bottomNavigationBar: widget.bottomNavigationBar,
  65. body: _WebviewPlaceholder(
  66. onRectChanged: (Rect value) {
  67. if (_rect == null) {
  68. _rect = value;
  69. webviewReference.launch(
  70. widget.url,
  71. headers: widget.headers,
  72. withJavascript: widget.withJavascript,
  73. clearCache: widget.clearCache,
  74. clearCookies: widget.clearCookies,
  75. enableAppScheme: widget.enableAppScheme,
  76. userAgent: widget.userAgent,
  77. rect: _rect,
  78. withZoom: widget.withZoom,
  79. withLocalStorage: widget.withLocalStorage,
  80. withLocalUrl: widget.withLocalUrl,
  81. scrollBar: widget.scrollBar,
  82. );
  83. } else {
  84. if (_rect != value) {
  85. _rect = value;
  86. _resizeTimer?.cancel();
  87. _resizeTimer = Timer(const Duration(milliseconds: 250), () {
  88. // avoid resizing to fast when build is called multiple time
  89. webviewReference.resize(_rect);
  90. });
  91. }
  92. }
  93. },
  94. child: const Center(
  95. child: CircularProgressIndicator(),
  96. ),
  97. ),
  98. );
  99. }
  100. }
  101. class _WebviewPlaceholder extends SingleChildRenderObjectWidget {
  102. const _WebviewPlaceholder({
  103. Key key,
  104. @required this.onRectChanged,
  105. Widget child,
  106. }) : super(key: key, child: child);
  107. final ValueChanged<Rect> onRectChanged;
  108. @override
  109. RenderObject createRenderObject(BuildContext context) {
  110. return _WebviewPlaceholderRender(
  111. onRectChanged: onRectChanged,
  112. );
  113. }
  114. @override
  115. void updateRenderObject(BuildContext context, _WebviewPlaceholderRender renderObject) {
  116. renderObject..onRectChanged = onRectChanged;
  117. }
  118. }
  119. class _WebviewPlaceholderRender extends RenderProxyBox {
  120. ValueChanged<Rect> _callback;
  121. Rect _rect;
  122. _WebviewPlaceholderRender({
  123. RenderBox child,
  124. ValueChanged<Rect> onRectChanged,
  125. }) : _callback = onRectChanged,
  126. super(child);
  127. Rect get rect => _rect;
  128. set onRectChanged(ValueChanged<Rect> callback) {
  129. if (callback != _callback) {
  130. _callback = callback;
  131. notifyRect();
  132. }
  133. }
  134. void notifyRect() {
  135. if (_callback != null && _rect != null) {
  136. _callback(_rect);
  137. }
  138. }
  139. @override
  140. void paint(PaintingContext context, Offset offset) {
  141. super.paint(context, offset);
  142. final rect = offset & size;
  143. if (_rect != rect) {
  144. _rect = rect;
  145. notifyRect();
  146. }
  147. }
  148. }