I want to implement the below UI in my MAUI application (header and footer sections are not added):
Below is my code (header and footer sections are not added): Webview to show HTML content(with a background image), Audio frame with previous, play and next options and finally a footer image.
<Frame
Margin="10,0,10,0"
x:Name="android_uwp_layout"
IsVisible="False"
Padding="0"
CornerRadius="20"
Grid.Row="1">
<ScrollView
x:Name="android_scroll_view"
Orientation="Vertical"
VerticalOptions="FillAndExpand">
<VerticalStackLayout Spacing="10">
<!-- Background image with WebView -->
<Grid>
<Image Aspect="Fill" HorizontalOptions="FillAndExpand" Source="ic_daily_reading_new_bg_xx.png"/>
<WebView
x:Name="mywebview"
BackgroundColor="Transparent"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Navigated="OnWebViewNavigated"/>
</Grid>
<!-- Audio frame (Appears after WebView content) -->
<Frame
x:Name="android_audio_frame"
BackgroundColor="#666664"
Padding="0"
CornerRadius="{OnIdiom Phone=30, Tablet=45, Desktop=30}"
Margin="0,10,0,15"
HorizontalOptions="CenterAndExpand"
VerticalOptions="EndAndExpand">
//Audio frame UI with previous, play and next options
</Frame>
<!-- Footer image (Appears at the bottom) -->
<ffimageloading:CachedImage
Aspect="AspectFit"
HorizontalOptions="Fill"
VerticalOptions="End"
Source="ic_jesus_xx.png"/>
</VerticalStackLayout>
</ScrollView>
</Frame>
I integrated the HTML content to webview like below: (Added custom font and added a different color for header contents)
string description = Details.description;
string htmlContent = $@"
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'/>
<style>
@font-face {{
font-family: 'PoppinsLight';
src: url('file:///android_asset/fonts/Poppins-Light.ttf');
}}
html, body {{
font-family: 'PoppinsLight', Arial, sans-serif;
margin: 0;
padding: 5;
line-height: 1.6;
overflow-x: hidden;
height: 100%;
}}
h4 {{
color: #679E18;
}}
</style>
</head>
<body>
{description}
</body>
</html>";
var htmlSource = new HtmlWebViewSource
{
Html = htmlContent
};
mywebview.Source = htmlSource;
Everything is working fine when load data initially. My Problem is when refreshing the content via API either blank space is showing in webview bottom or the entire webview content is not showing on the UI. The initially loaded height is not changing when loading the new content.
I have added Navigated
event for webview, but it only fires when loading the data on initial time.
private async void OnWebViewNavigated(object sender, WebNavigatedEventArgs e)
{
await Task.Delay(500); // Allow time for content to load
string js = "document.body.scrollHeight";
var height = await mywebview.EvaluateJavaScriptAsync(js);
if (double.TryParse(height, out double newHeight) && newHeight > 0)
{
mywebview.HeightRequest = newHeight; // Set WebView height dynamically
}
}
Please check this video for a clear understanding.
I tried creating a new function with the OnWebViewNavigated
logic like below:
//setting html data to webview
mywebview.Source = htmlSource;
await Task.Delay(500);
await AdjustWebViewHeight();
private async Task AdjustWebViewHeight()
{
string js = "document.body.scrollHeight";
var height = await mywebview.EvaluateJavaScriptAsync(js);
if (double.TryParse(height, out double newHeight) && newHeight > 0)
{
mywebview.HeightRequest = newHeight;
}
}
But at that time the UI completely breaks. Showing blank space on top and font styles are changing with that approach. In this video I have added what kind of issues with the new logic I tried.
Please suggest a solution to update the webview height based on the content without affecting the font family and blank spaces.
I want to implement the below UI in my MAUI application (header and footer sections are not added):
Below is my code (header and footer sections are not added): Webview to show HTML content(with a background image), Audio frame with previous, play and next options and finally a footer image.
<Frame
Margin="10,0,10,0"
x:Name="android_uwp_layout"
IsVisible="False"
Padding="0"
CornerRadius="20"
Grid.Row="1">
<ScrollView
x:Name="android_scroll_view"
Orientation="Vertical"
VerticalOptions="FillAndExpand">
<VerticalStackLayout Spacing="10">
<!-- Background image with WebView -->
<Grid>
<Image Aspect="Fill" HorizontalOptions="FillAndExpand" Source="ic_daily_reading_new_bg_xx.png"/>
<WebView
x:Name="mywebview"
BackgroundColor="Transparent"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Navigated="OnWebViewNavigated"/>
</Grid>
<!-- Audio frame (Appears after WebView content) -->
<Frame
x:Name="android_audio_frame"
BackgroundColor="#666664"
Padding="0"
CornerRadius="{OnIdiom Phone=30, Tablet=45, Desktop=30}"
Margin="0,10,0,15"
HorizontalOptions="CenterAndExpand"
VerticalOptions="EndAndExpand">
//Audio frame UI with previous, play and next options
</Frame>
<!-- Footer image (Appears at the bottom) -->
<ffimageloading:CachedImage
Aspect="AspectFit"
HorizontalOptions="Fill"
VerticalOptions="End"
Source="ic_jesus_xx.png"/>
</VerticalStackLayout>
</ScrollView>
</Frame>
I integrated the HTML content to webview like below: (Added custom font and added a different color for header contents)
string description = Details.description;
string htmlContent = $@"
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'/>
<style>
@font-face {{
font-family: 'PoppinsLight';
src: url('file:///android_asset/fonts/Poppins-Light.ttf');
}}
html, body {{
font-family: 'PoppinsLight', Arial, sans-serif;
margin: 0;
padding: 5;
line-height: 1.6;
overflow-x: hidden;
height: 100%;
}}
h4 {{
color: #679E18;
}}
</style>
</head>
<body>
{description}
</body>
</html>";
var htmlSource = new HtmlWebViewSource
{
Html = htmlContent
};
mywebview.Source = htmlSource;
Everything is working fine when load data initially. My Problem is when refreshing the content via API either blank space is showing in webview bottom or the entire webview content is not showing on the UI. The initially loaded height is not changing when loading the new content.
I have added Navigated
event for webview, but it only fires when loading the data on initial time.
private async void OnWebViewNavigated(object sender, WebNavigatedEventArgs e)
{
await Task.Delay(500); // Allow time for content to load
string js = "document.body.scrollHeight";
var height = await mywebview.EvaluateJavaScriptAsync(js);
if (double.TryParse(height, out double newHeight) && newHeight > 0)
{
mywebview.HeightRequest = newHeight; // Set WebView height dynamically
}
}
Please check this video for a clear understanding.
I tried creating a new function with the OnWebViewNavigated
logic like below:
//setting html data to webview
mywebview.Source = htmlSource;
await Task.Delay(500);
await AdjustWebViewHeight();
private async Task AdjustWebViewHeight()
{
string js = "document.body.scrollHeight";
var height = await mywebview.EvaluateJavaScriptAsync(js);
if (double.TryParse(height, out double newHeight) && newHeight > 0)
{
mywebview.HeightRequest = newHeight;
}
}
But at that time the UI completely breaks. Showing blank space on top and font styles are changing with that approach. In this video I have added what kind of issues with the new logic I tried.
Please suggest a solution to update the webview height based on the content without affecting the font family and blank spaces.
Share Improve this question asked Mar 15 at 10:53 Matthew PansMatthew Pans 8751 gold badge11 silver badges29 bronze badges 8 | Show 3 more comments1 Answer
Reset to default 1- Update
I share a workaround to adjust height when changing the WebView Source using Maui Handler.
In code behind, first we customize a ModifyWebView
Handler in constructor.
We create a CustomWebViewClient
class and set it to platformWebView
.
public DailyReadingPage()
{
InitializeComponent();
ModifyWebView();
...
CallDailyReading(htmldata);
}
void ModifyWebView()
{
Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
#if ANDROID
if (handler.PlatformView is global::Android.Webkit.WebView platformWebView)
{
platformWebView.SetWebViewClient(new CustomWebViewClient(this.mywebview));
}
#endif
});
}
Here is the code for CustomWebViewClient
class, you can place it just in code behind,
#if ANDROID
public class CustomWebViewClient : WebViewClient
{
Microsoft.Maui.Controls.WebView mywebview;
public CustomWebViewClient(Microsoft.Maui.Controls.WebView webView)
{
mywebview = webView;
//mywebview.HeightRequest = 0;
}
public async override void OnPageFinished(Android.Webkit.WebView view, string url)
{
mywebview.HeightRequest = 0;
await Task.Delay(500); // Allow time for content to load
string js = "document.body.scrollHeight";
var height = await mywebview.EvaluateJavaScriptAsync(js);
if (double.TryParse(height, out double newHeight) && newHeight > 0)
{
mywebview.HeightRequest = newHeight; // Set WebView height dynamically
}
base.OnPageFinished(view, url);
}
}
#endif
Just set the height: 100%
is okay.
It will adjust the size then.
By the way, though it seems not necessary, you could also try adding the PropertyChanged
event for the WebView and implement it. The code is shown below for your reference, hope it helps!
<WebView PropertyChanged="mywebview_PropertyChanged"
x:Name="mywebview"
and implement it in code behind,
private void mywebview_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
#if ANDROID
if (e.PropertyName == "Source")
{
if (this.mywebview.Handler != null)
(this.mywebview.Handler.PlatformView as Android.Webkit.WebView).SetWebViewClient(new CustomWebViewClient(this.mywebview));
}
#endif
}
webViewRenderer
? Could you please share a Minimal, Reproducible Example with all private data removed? – Felix Shen Commented Mar 17 at 2:52height is increasing gradually without stopping.
Is it only happening in this demo? – Felix Shen Commented Mar 17 at 7:41