【问题标题】:How to detect webview scrolled to bottom?如何检测滚动到底部的webview?
【发布时间】:2021-06-29 05:57:49
【问题描述】:

我想知道用户何时结束在显示条款和条件的 Web 视图上的滚动,以便仅在用户阅读此内容时显示“接受”按钮。

<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>

public class HtmlSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var html = new HtmlWebViewSource();
        if (value != null)
        {
            html.Html = value.ToString();
        }
        return html;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我尝试使用 Renderer 来实现这一点,但在 iOS 中 WkWebViewRenderer 没有 WebViewRenderer 中可用的 Scrolled() 方法。

有没有办法在 Xamarin.Forms 中实现这一点?

【问题讨论】:

    标签: xamarin xamarin.forms webview xamarin.android xamarin.ios


    【解决方案1】:

    我也有适用于 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);
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      WKWebView 里面有一个属性ScrollView,所以我们可以用它覆盖委托。

      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

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多