question

EJ-5254 avatar image
0 Votes"
EJ-5254 asked ColeXia-MSFT answered

WebView inside ScrollView

Hi,

I've WebView inside ScrollView together with other controls like labels above WebView. When I scroll only WebView scrolls, how can I make so whole screen scrolls?

 <ScrollView>
     <StackLayout VerticalOptions="FillAndExpand">
          <Label Text="Hello"/>
       <WebView VerticalOptions="FillAndExpand">
           <WebView.Source>
               <HtmlWebViewSource Html="{Binding MyHTMLText}" />
           </WebView.Source>
       </WebView>
     </StackLayout>
 </ScrollView>

I'm trying to achieve same thing as Gmail app does. What is interesting that in Gmail app when you scroll up scrollbar only appears when email header is completely hidden, so looks like they somehow combined email header controls and WebView, but not in ScrollView.

dotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

ColeXia-MSFT avatar image
0 Votes"
ColeXia-MSFT answered EJ-5254 commented

Hello,

Welcome to Microsoft Q&A!

Do you simply want to disable the webview scrolling ? If so you can do it with custom renderer in each platform.

iOS

[assembly: ExportRenderer(typeof(WebView), typeof(MyRenderer))]
namespace FormsA.iOS
{
    public class MyRenderer : WkWebViewRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            this.ScrollView.ScrollEnabled = false;
        }
    }
}

Android

[assembly: ExportRenderer(typeof(WebView), typeof(MyRenderer))]
namespace FormsA.Droid
{
    class MyWebview  : WebView
    {
        public MyWebview(Context context):base(context)
        {

        }

        public MyWebview(Context context, IAttributeSet att ) : base(context,att)
        {

        }

        public MyWebview(Context context, IAttributeSet att,int defStyle) : base(context,att,defStyle)
        {

        }

        protected override void OnScrollChanged(int l, int t, int oldl, int oldt)
        {
            base.OnScrollChanged(l, t, oldl, oldt);

            ScrollTo(l, 0);
        }

    }

    class MyRenderer : WebViewRenderer
    {

        Context _context;
        public MyRenderer(Context context):base(context)
        {
            _context = context;
        }
        protected override Android.Webkit.WebView CreateNativeControl()
        {
            return new MyWebview(_context);

        }
    }
}

Best Regards,
Cole Xia


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you, it was good idea to disable WebView scrolling! In iOS custom renderer I also set HeightRequest of my custom webview to the height of scroll contents and it works fine now! Hopefully should be able to do the same on Android.

 public override void DidFinishNavigation( WKWebView webView, WKNavigation navigation )
 {
        wv.HeightRequest = (double)webView.ScrollView.ContentSize.Height;
 }
1 Vote 1 ·

Hi,

Thank you for you answer. If I disable webview , but it's contents exceeds screen height, how can I make it scroll?
What I'm trying to achieve is to scroll whole page together with webview, but webview contents should scroll as well.

As I mentioned previously looks like Gmail app first scrolls header view and once it's hidden webview starts scrolling, I've no idea how to achieve this.

0 Votes 0 ·

Hi Cole,

Android code doesn't compile, for example MyWebview base(context) shows that WebView doesn't have base class with 1 parameter? Also

 protected override Android.Webkit.WebView CreateNativeControl()
         {
             return new MyWebview(_context);
         }

can't return MyWebView as Android.Webkit etc.

0 Votes 0 ·

Did you check my code for android above ?

MyWebview inherits from Android.Webkit.WebView and you should add the constructor for it .

class MyWebview  : WebView
    {
        public MyWebview(Context context):base(context)
        {
        }
0 Votes 0 ·

Sorry, didn't realise WebView inherits from Android.Webkit.WebView and this was messing it all up. So now when I run the app I can't scroll WebView as expected, but my WebView contents is longer than screen height, how can I set it's height to the size of it's contents?

0 Votes 0 ·
ColeXia-MSFT avatar image
0 Votes"
ColeXia-MSFT answered

Try to get height from JSBridge and set on webview.


[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(MyRenderer))]
namespace FormsA.Droid
{
    public class JavascriptWebViewClient : FormsWebViewClient
    {
        public JavascriptWebViewClient(MyRenderer renderer) : base(renderer)
        {
        
        }

        public override void OnPageFinished(Android.Webkit.WebView view, string url)
        {
            base.OnPageFinished(view, url);
            view.LoadUrl("javascript:myApp.resize(document.body.scrollHeight)");
        }
    }

    public class JSBridge : Java.Lang.Object
    {
        public Xamarin.Forms.WebView _webview;

        public JSBridge(Xamarin.Forms.WebView webview)
        {
            _webview = webview;
        }

        [JavascriptInterface]
        [Export("resize")]
        public void resize(float height)
        {

        
            _webview.HeightRequest = height * MainActivity.Instance.ApplicationContext.Resources.DisplayMetrics.Density ;
        }
    }

    public class MyRenderer : WebViewRenderer 
    {

        Context _context;
        public MyRenderer(Context context):base(context)
        {
            _context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
            }
            if (e.NewElement != null)
            {
                Control.SetWebViewClient(new JavascriptWebViewClient(this));
                Control.AddJavascriptInterface(new JSBridge(Element), "myApp");
                Control.LoadUrl("https://dotnet.microsoft.com/apps/xamarin");
            }
        }

    }
}


//MainActivity

  public static MainActivity Instance;


        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);

            Instance = this;  add this line



Refer to https://stackoverflow.com/a/25187094/8187800 .

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.