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 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?
Share Improve this question asked Feb 7 at 7:36 Matthew PansMatthew Pans 7931 gold badge9 silver badges27 bronze badges1 Answer
Reset to default 0I 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;