I have an image and custom webview inside a stack and surrounded by a frame like below:
<Frame
Padding="5"
CornerRadius="20"
Margin="0,10,0,0"
Grid.Row="1"
x:Name="android_webview_frame"
BackgroundColor="#0091DA"
IsVisible="False">
<StackLayout
BackgroundColor="#0091DA">
<Image
x:Name="android_saint_image"
Aspect="AspectFit"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
IsVisible="False"
Margin="5"/>
<local:DailySaintAndroidWebView
x:Name="android_webview"
BackgroundColor="#0091DA"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</Frame>
In webview I am showing html data and I need to implement scrolling for the entire layout. Currently if i scroll only the webview contents are scrollable. The image is not scroll to top. I have added a scrollview like below but that is not working.
<Frame
Padding="5"
CornerRadius="20"
Margin="0,10,0,0"
Grid.Row="1"
x:Name="android_webview_frame"
BackgroundColor="#0091DA"
IsVisible="False">
<ScrollView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout
BackgroundColor="#0091DA">
<Image
x:Name="android_saint_image"
Aspect="AspectFit"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
IsVisible="False"
Margin="5"/>
<local:DailySaintAndroidWebView
x:Name="android_webview"
BackgroundColor="#0091DA"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</ScrollView>
</Frame>
The issue here is that WebView has its own internal scrolling mechanism, which conflicts with the ScrollView. So I tried to disable scrolling inside the WebView so that the entire ScrollView can handle the scrolling.
Android customwebview:
[assembly: ExportRenderer(typeof(DailySaintAndroidWebView), typeof(DailySaintAndroidRenderer))]
namespace OfficeName.Droid.Renderer
{
public class DailySaintAndroidRenderer : WebViewRenderer
{
public DailySaintAndroidRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Microsoft.Maui.Controls.WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// Set default font size
Control.Settings.DefaultFontSize = 25;
Control.Settings.JavaScriptEnabled = true; // Ensure JavaScript is enabled
// Disable WebView scrolling
Control.SetOnTouchListener(new CustomTouchListener());
// Inject CSS to change text color to white
string changeTextColorScript = @"
let style = document.createElement('style');
style.innerHTML = 'body, p, h1, h2, h3, h4, h5, h6 { color: white !important; background-color: #0091DA !important; }';
document.head.appendChild(style);
";
Control.SetWebViewClient(new CustomWebViewClient(changeTextColorScript));
}
}
private class CustomWebViewClient : WebViewClient
{
private readonly string _script;
public CustomWebViewClient(string script)
{
_script = script;
}
public override void OnPageFinished(Android.Webkit.WebView view, string url)
{
base.OnPageFinished(view, url);
// Execute JavaScript to inject the CSS
view.EvaluateJavascript(_script, null);
}
}
}
public class CustomTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
{
public bool OnTouch(View v, MotionEvent e)
{
if (e.Action == MotionEventActions.Move)
{
v.Parent?.RequestDisallowInterceptTouchEvent(false);
}
return false;
}
}
}
ios customwebview
[assembly: ExportRenderer(typeof(DailySaintWebView), typeof(DailySaintWebViewRenderer))]
namespace OfficeName.Platforms.iOS.Renderer
{
public class DailySaintWebViewRenderer : ViewRenderer<DailySaintWebView, WKWebView>
{
WKWebView _wkWebView;
protected override void OnElementChanged(ElementChangedEventArgs<DailySaintWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var config = new WKWebViewConfiguration();
config.AllowsInlineMediaPlayback = true;
_wkWebView = new WKWebView(Frame, config);
//transparent background
_wkWebView = new WKWebView(CGRect.Empty, config);
_wkWebView.BackgroundColor = UIColor.Clear;
_wkWebView.ScrollView.BackgroundColor = UIColor.Clear;
_wkWebView.Opaque = false;
_wkWebView.NavigationDelegate = new MyNavigationDelegate();
SetNativeControl(_wkWebView);
}
}
public class MyNavigationDelegate : WKNavigationDelegate
{
public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
string fontSize = Device.Idiom == TargetIdiom.Phone ? "500%" : "750%";
string adjustTextSizeScript = $"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '{fontSize}';";
string changeTextColorScript = @"
let style = document.createElement('style');
style.innerHTML = 'body, p, h1, h2, h3, h4, h5, h6 { color: white !important; }';
document.head.appendChild(style);
";
WKJavascriptEvaluationResult handler = (NSObject result, NSError err) =>
{
if (err != null)
{
System.Console.WriteLine(err);
}
if (result != null)
{
System.Console.WriteLine(result);
}
};
webView.EvaluateJavaScript(adjustTextSizeScript, handler);
webView.EvaluateJavaScript(changeTextColorScript, handler);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Url")
{
string finalHtml = Element.Url.Replace("width=\"640\"", "width=\"1000\"");
Control.LoadHtmlString(finalHtml, null);
}
}
}
}
But it is not working, so how can I disable scrolling of custom webview in android and ios and make the scrollview to scroll the entire data?
I think defining your layout properly will stretch the WebView and its content, allowing you to scroll the entire page using MAUI Scrollview as intended. You can test this with a default .NET MAUI screen like this:
<ScrollView>
<VerticalStackLayout
Padding="30,0"
Spacing="25">
<Image
Source="dotnet_bot.png"
HeightRequest="185"
Aspect="AspectFit"
SemanticProperties.Description="dot net bot in a race car number eight" />
<Label
Text="Hello, World!"
Style="{StaticResource Headline}"
SemanticProperties.HeadingLevel="Level1" />
<Label
Text="Welcome to .NET Multi-platform App UI"
Style="{StaticResource SubHeadline}"
SemanticProperties.HeadingLevel="Level2"
SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
<Button
x:Name="CounterBtn"
Text="Click me"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked"
HorizontalOptions="Fill" />
<WebView
Source="https://www.pexels.com/"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</VerticalStackLayout>
</ScrollView>
Disabling Scrolling in WebView:
If you want to disable scrolling inside the WebView so that the ScrollView can handle scrolling for the entire page, try the following approaches:
For Android:
if (Control is global::Android.Webkit.WebView platformWebView)
{
platformWebView.SetOnTouchListener(new WebViewTouchListener());
}
// Custom touch listener class
public class WebViewTouchListener : Java.Lang.Object, global::Android.Views.View.IOnTouchListener
{
public bool OnTouch(Android.Views.View? v, global::Android.Views.MotionEvent? e)
{
return e.Action == global::Android.Views.MotionEventActions.Move;
}
}
For iOS:
_wkWebView.ScrollView.ScrollEnabled = false;