Skip to content

Instantly share code, notes, and snippets.

@SPodjasek
Created June 18, 2019 14:57
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save SPodjasek/2f43fe45076976c16d830c749f992a1a to your computer and use it in GitHub Desktop.
Save SPodjasek/2f43fe45076976c16d830c749f992a1a to your computer and use it in GitHub Desktop.
import 'dart:math' show max;
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:webview_flutter/webview_flutter.dart';
class ExpandableWebView extends StatefulWidget {
final String url;
final EdgeInsets padding;
ExpandableWebView(
this.url, {
Key key,
this.padding = const EdgeInsets.all(0),
}) : super(key: key);
@override
_ExpandableWebViewState createState() => _ExpandableWebViewState();
}
class _ExpandableWebViewState extends State<ExpandableWebView> {
double contentHeight = 0;
bool loaded = false;
@override
Widget build(BuildContext context) {
print('[webView/build] url: ${widget.url}');
return Container(
padding: widget.padding,
width: double.infinity,
height: max(MediaQuery.of(context).size.height, contentHeight),
child: Stack(
alignment: Alignment.topCenter,
children: [
_buildWebView(context),
if (!loaded)
InfiniteProgressIndicator(
padding: EdgeInsets.symmetric(
vertical: 16.0,
),
)
],
));
}
Widget _buildWebView(BuildContext context) {
return WebView(
initialUrl: widget.url,
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: Set.from([
JavascriptChannel(
name: 'extents',
onMessageReceived: (JavascriptMessage message) {
print('[webView/javascriptChannels] ${message.message}');
setState(() {
contentHeight = double.parse(message.message);
});
},
)
]),
onPageFinished: (String url) {
print('[webView/onPageFinished] finished loading "$url"');
setState(() {
loaded = true;
});
},
onWebViewCreated: (WebViewController ctrl) {
print('[webView/onWebViewCreated] created');
},
);
}
}
<script type="text/javascript">window.extents.postMessage(document.body.offsetHeight);</script>
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class InfiniteProgressIndicator extends StatelessWidget {
final EdgeInsets padding;
const InfiniteProgressIndicator({
Key key,
this.padding = const EdgeInsets.all(0),
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: padding,
child: Platform.isAndroid
? CircularProgressIndicator(
value: null,
valueColor:
AlwaysStoppedAnimation<Color>(Theme.of(context).primaryColor),
strokeWidth: 2.0,
)
: CupertinoActivityIndicator(
radius: 20.0,
),
);
}
}
@sboicu
Copy link

sboicu commented May 25, 2020

do you have an example or something? I try to use your solution but it`s not working for me. I am not sure what I am doing wrong. An example would be highly appreciate.

@krishnaSoni2113
Copy link

I am also facing the same issue and I tried your solution but not working for me as well.

@DFelten
Copy link

DFelten commented Jul 30, 2020

App is still crashing on Android when setting the height to a high value.

@mobikats
Copy link

mobikats commented Nov 9, 2020

Testing on iOS Simulator, the javascript channel section never runs and the contentHeight is never set :(

@mobikats
Copy link

Ok I was being dense - I hadn't actually injected the JS into the incoming HTML :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment