最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

MAUI: How to disable scrollview of custom webview in android and ios? - Stack Overflow

programmeradmin0浏览0评论

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 badges
Add a comment  | 

1 Answer 1

Reset to default 0

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 &#10;.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;
发布评论

评论列表(0)

  1. 暂无评论