I want to create a UI with a Label(title), image(saint image) and a webview(to show HTMl content). When scroll I want to scroll the entire item, not the webview contents only. After all these I need a section to show the audio player with previous, next and play options. So I created a UI like below:
<!-- Android view -->
<Frame
Padding="5"
CornerRadius="20"
Margin="0,10,0,0"
Grid.Row="1"
x:Name="android_webview_frame"
BackgroundColor="#0091DA"
IsVisible="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollView
x:Name="android_scroll_view"
Grid.Row="0"
Orientation="Vertical"
VerticalOptions="FillAndExpand">
<VerticalStackLayout
Grid.Row="0"
Padding="5"
Spacing="10"
VerticalOptions="FillAndExpand"
BackgroundColor="#0091DA">
<Label
<!-- Title label -->
</Label>
<!-- Saint image -->
<Grid
IsVisible="False"
x:Name="image_layout">
<!-- Saint Image with name on top of saint-->
</Grid>
<!-- Main content -->
<WebView
x:Name="android_webview"
BackgroundColor="#0091DA"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
</WebView>
</VerticalStackLayout>
</ScrollView>
<!-- Audio border -->
<Border
x:Name="android_audio_border"
Grid.Row="1"
BackgroundColor="#014F78"
StrokeThickness="0"
Padding="0"
Margin="15"
HorizontalOptions="FillAndExpand"
VerticalOptions="EndAndExpand">
<Border.StrokeShape>
<RoundRectangle CornerRadius="30"/>
</Border.StrokeShape>
</Border>
</Grid>
</Frame>
Expected UI:
Everything is working as expected when loading content initially. My problem is When loading a different day's data, there is blank space on the bottom of the webview.
Below is the logic to show content on webview: I set a custom font and white text color for the webview contents.
string description = Details.description;
// Define custom CSS to set font and text color
string htmlContent = $@"
<html>
<head>
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
<style>
@font-face {{
font-family: 'Poppins';
src: url('file:///android_asset/fonts/Poppins-Regular.ttf'); /* For Android */
}}
body {{
background-color: #0091DA; /* Match WebView background */
color: white; /* Set text color */
font-family: 'Poppins', sans-serif;
padding: 10px;
font-size: 20px; /* Increase font size */
line-height: 1.6; /* Improve readability */
}}
h4, h5, p {{
color: white;
}}
</style>
</head>
<body>
{description}
</body>
</html>";
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = htmlContent;
android_webview.Source = htmlSource;
Please watch this video for a clear understanding.
I try adding a Navigated
event for webview
but when adding that the content is not visible on the UI. Please suggest a solution to remove the empty space after webview
when loading new data.
You may try using Handler to customize the WebView. You may refer to Customize controls with handlers.
And implement it in code behind,
public DailySaintPage()
{
InitializeComponent();
ModifyWebView();
...
CallDailySaint(data);
}
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.android_webview));
}
#endif
});
}
And here is the code for CustomWebViewClient
class,
#if ANDROID
public class CustomWebViewClient : WebViewClient
{
Microsoft.Maui.Controls.WebView mywebview;
public CustomWebViewClient(Microsoft.Maui.Controls.WebView webView)
{
mywebview = webView;
}
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
And you don't need custom renderer any more.
Hope it helps!