I'm creating an app that is getting a dynamic HTML website from an API. My main challenge is that I need to auto-adjust the height
of the WebView
in real-time because the property android:layout_height="wrap_content"
is not working as expected and doesn't auto-adjust its height
is always 0dp
, and it's never shown.
The API that I consume can return a simple text like this:
<p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p>
Or complex HTMLs with images, tables, minor formatting, etc.
From my side, I have tried to set the WebView
height as wrap_content
(as explained before) and as a workaround, and at the same time, I hid it before loading, reloaded it after it was done, and displayed it again after the content was fully loaded, but nothing worked properly. The height
was either 0dp
or a small number like 32dp
, pretty much meaningless and invisible since almost every HTML is long.
This is my current code with some potential examples to test:
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="@+id/llOverview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/min_val"
android:orientation="vertical">
<ProgressBar
android:id="@+id/indeterminateBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:indeterminate="true"
android:max="100"
android:layout_height="wrap_content" />
<TextView
android:layout_marginTop="@dimen/min_half_val"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/text_size"
android:id="@+id/lblDescription" />
<android.webkit.WebView
android:id="@+id/webViewExtra"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
C#:
var lblDescription = FindViewById<TextView>(Resource.Id.lblDescription);
lblDescription.Text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Potenti nullam ac tortor vitae purus faucibus ornare. Tellus elementum sagittis vitae et leo duis. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Elementum curabitur vitae nunc sed velit dignissim sodales ut. Vitae aliquet nec ullamcorper sit amet risus nullam eget. Quis imperdiet massa tincidunt nunc pulvinar sapien et ligula. Quam adipiscing vitae proin sagittis. Bibendum at varius vel pharetra vel turpis nunc. Bibendum at varius vel pharetra vel. Id diam vel quam elementum. Magna etiam tempor orci eu lobortis elementum nibh tellus. Ligula ullamcorper malesuada proin libero nunc. Gravida quis blandit turpis cursus. Ut pharetra sit amet aliquam id diam maecenas. Nisl rhoncus mattis rhoncus urna neque. Tempus egestas sed sed risus pretium quam vulputate dignissim. Et netus et malesuada fames ac. Malesuada fames ac turpis egestas maecenas pharetra convallis.";
var webView = FindViewById<Android.Webkit.WebView>(Resource.Id.webViewExtra);
webView.Visibility = ViewStates.Gone;
webView.Settings.VerticalScrollBarEnabled = true;
webView.Settings.JavaScriptEnabled = true;
var html = "<p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p><p>Lorem ipsum dolor sit amet consectetur adipiscing elit, malesuada per consequat conubia accumsan vulputate tincidunt, porttitor cum cras pretium diam inceptos. Augue fringilla id laoreet metus quisque eu accumsan ultrices fusce, vel hendrerit phasellus mollis arcu consequat risus suscipit, nostra orci lobortis at quis sed integer cubilia. Quisque turpis congue euismod class tristique magna at eros aenean quam, cum facilisis malesuada per auctor cubilia leo ultrices pharetra, praesent habitant ut nec feugiat velit pulvinar libero tellus.</p>";
if (!string.IsNullOrEmpty(html))
{
html = $@"<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body style='margin: 0px; background: #fafafa'>{html}</body>
</html>";
webView.SetWebViewClient(new JSOverviewHelper());
webView.LoadData(html, "text/html", "UTF-8");
webView.Reload();
}
public class JSOverviewHelper : WebViewClient
{
public override void OnPageFinished(WebView webView, string url)
{
base.OnPageFinished(webView, url);
webView.Visibility = Android.Views.ViewStates.Visible;
}
}
In addition to that, I already tried to calculate the height
using a JS function, and didn't work as expected. The returned height
tended to be the current height
of the WebView + 1px
. However, if I ran the same function using chrome://inspect
then it returned the correct value that was odd.
This is the function to test this experiment using the OnPageFinished
event in the WebView
:
public override void OnPageFinished(WebView webView, string url)
{
base.OnPageFinished(webView, url);
webView.Visibility = ViewStates.Visible;
Thread.Sleep(1000);
webView.EvaluateJavascript(@"(function() {
var body = document.body,
html = document.documentElement;
return Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
})();", new WebViewValueCallback(webView));
}
public class WebViewValueCallback : Object, IValueCallback
{
private readonly WebView webView;
public WebViewValueCallback(WebView webView)
{
this.webView = webView;
}
public void OnReceiveValue(Object value)
{
var result = Convert.ToString(value);
ViewGroup.LayoutParams vc = webView.LayoutParameters;
vc.Height = int.Parse(Convert.ToString(value));
webView.LayoutParameters = vc;
}
}
Additionally, I tried using the OnPageCommitVisible
(it was triggered before OnPageFinished
) and OnProgressChanged
using a custom class based on WebChromeClient
as suggested here, and when it reached 100% the JS function still returned a different value than the expected one, it always returned either 0 or the current height of WebView + 1px
as before.
What else did I try? I set a predefined height in the WebView
to test the app, created a static page, and loaded the data with JS, but still, the returned height was incorrect.
Any idea how I can adjust the height to the latest one after it's loaded? Thanks.
P.S.:
- If you know how to fix it in Java or Kotlin, I most likely will know how to transform it into C# code. It's still a valid answer from my side.
- The
TextView
is mandatory because it shows an extract before the website that can be optional. Therefore, it cannot be removed.