xamarin 如何检测Webview滚动到底部?

bgibtngc  于 5个月前  发布在  其他
关注(0)|答案(3)|浏览(81)

我想知道当用户已经结束了一个Webview上的滚动显示条款和条件显示一个“接受”按钮,只有当用户阅读此。

<StackLayout Spacing="0" BackgroundColor="{StaticResource WhiteColor}">
    <CustomView:HeaderView VerticalOptions="Start" LeftImageSource="{Binding LeftImage}" RightImageSource="{Binding RightImage}" LeftCommand="{Binding LeftClickCommand}" RightCommand="{Binding RightClickCommand}" HeaderText="{Binding ScreenTitle}" PrevText="{Localize:ETranslate PrevText}" />
    <WebView Source="{Binding Html, Converter={StaticResource HtmlSourceConverter}}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</StackLayout>

个字符
我曾尝试使用Renderer来实现这一点,但在iOS中WkWebViewRenderer没有WebViewRenderer中可用的Scrolled()方法。
在Xamarin.Forms中有什么方法可以实现这一点吗?

js5cn81o

js5cn81o1#

WKWebView内部有一个属性ScrollView,所以我们可以用它覆盖Delegate。

WKWebViewRenderer代码

[assembly: ExportRenderer(typeof(WebView), typeof(MyRenderer))]
namespace FormsA.iOS
{
    public class MyDelegate : UIScrollViewDelegate
    {
        public override void Scrolled(UIScrollView scrollView)
        {
         
            if(scrollView.ContentOffset.Y >= scrollView.ContentSize.Height - scrollView.Frame.Size.Height)
            {
                 //here rearch bottom 
            }
            else if(scrollView.ContentOffset.Y < scrollView.ContentSize.Height)
            {
                
            }

            
        }
    }

    public class MyRenderer: WkWebViewRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            this.ScrollView.Delegate = new MyDelegate();
        }
    }
}

字符串
它在我这边工作得很好,参考https://stackoverflow.com/a/52872317/8187800

5uzkadbs

5uzkadbs2#

我已经得到了Android的解决方案以及.这里是整个解决方案,希望这可能是有帮助的人寻找相同的!

MyPage.xaml

<webview:ScrollWebView x:Name="webView" Source="{Binding Html, Converter={StaticResource HtmlSourceConverter}}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" IsBottomReached="{Binding IsShowAgreeButton}"/>

字符串

ScrollWebView控件

public class ScrollWebView : WebView
{
    public static BindableProperty IsBottomReachedProperty =
        BindableProperty.Create(nameof(IsBottomReached), typeof(bool), typeof(ScrollWebView), default(bool), BindingMode.TwoWay, propertyChanged: null);

    public bool IsBottomReached
    {
        get
        {
            return (bool)GetValue(IsBottomReachedProperty);
        }
        set
        {
            SetValue(IsBottomReachedProperty, value);
        }
    }
}

Android:ScrollWebViewRenderer

[assembly: Xamarin.Forms.ExportRenderer(typeof(ScrollWebView), typeof(ScrollWebViewRenderer))]
namespace MyApp.Droid
{
    public class ScrollWebViewRenderer : WebViewRenderer
    {
        public static ScrollWebView view = null;

        public ScrollWebViewRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            view = (ScrollWebView)Element;
            if (Control != null)
            {
                Control.ScrollChange += Control_ScrollChange;
            }
        }

        private void Control_ScrollChange(object sender, ScrollChangeEventArgs e)
        {
            var nativeWebView = e.V as global::Android.Webkit.WebView;
            int height = (int)Math.Floor(nativeWebView.ContentHeight * nativeWebView.Scale);
            int webViewheight = nativeWebView.Height;

            int cutOff = height - webViewheight;

            if (e.ScrollY >= cutOff)
            {
                view.IsBottomReached = true;
                System.Diagnostics.Debug.WriteLine("Bottom Reached");
            }
            else
            {
                view.IsBottomReached = false;
            }
        }
    }
}

iOS:ScrollWebViewRenderer

[assembly: ExportRenderer(typeof(ScrollWebView), typeof(ScrollWebViewRenderer))]
namespace MyApp.iOS.RendererClasses
{
    public class ScrollWebViewRenderer : WkWebViewRenderer
    {
        public static ScrollWebView view = null;
        
        public ScrollWebViewRenderer() { }

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
            view = (ScrollWebView)Element;

            MyDelegate myDel = new MyDelegate();
            myDel.ProcessCompleted += MyDel_ProcessCompleted;

            this.ScrollView.Delegate = myDel;
        }

        private void MyDel_ProcessCompleted(object sender, bool isScrolledToBottom)
        {
            view.IsBottomReached = isScrolledToBottom;
        }
    }

    public class MyDelegate : UIScrollViewDelegate
    {
        public event EventHandler<bool> ProcessCompleted;

        public override void Scrolled(UIScrollView scrollView)
        {
            if (scrollView.ContentOffset.Y >= scrollView.ContentSize.Height - scrollView.Frame.Size.Height)
            {
                System.Diagnostics.Debug.WriteLine("Bottom Reached");
                ProcessCompleted?.Invoke(this, true);
            }
            else
            {
                ProcessCompleted?.Invoke(this, false);
            }
        }
    }
}

vwoqyblh

vwoqyblh3#

在实现这个答案之后,https://stackoverflow.com/a/66931493/15125666我仍然在android渲染器上遇到麻烦,因为它没有检测到用户何时到达WebView的底部。
要解决这个问题,您需要在计算中添加一个缓冲区,这将在内容高度乘以比例时考虑任何潜在的浮点错误。
以下是Android:ScrollWebViewRenderer的更新代码

private void Control_ScrollChange(object sender, ScrollChangeEventArgs e)
    {
        var nativeWebView = e.V as global::Android.Webkit.WebView;
        int height = (int)(nativeWebView.ContentHeight * nativeWebView.Scale);            
        int webViewheight = nativeWebView.Height;
        int bottomThreshold = (int)Math.Floor(0.004 * webViewheight); // the number that I used 0.004 was what worked for me. you might need to adjust it for your use case.

        int cutOff = height - webViewheight - bottomThreshold;

        if (e.ScrollY >= cutOff)
        {
            view.IsBottomReached = true;
            System.Diagnostics.Debug.WriteLine("Bottom Reached");
        }
        else
        {
            view.IsBottomReached = false;
        }
    }

字符串
这里我添加了一个动态的bottomThresholdbuffer,并将其用于cutOff计算。它在计算中添加了一个小的buffer,以确保即使很小的差异也不会阻止到达底部的检测。

相关问题