You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Xamarin.Forms自定义WebView展示PDF:如何实现锚点滚动?

在Xamarin.Forms中实现PDF锚点跳转与滚动的解决方案

你提到的自定义UIWebView渲染器无法通过Eval执行滚动脚本的问题,核心原因在于旧版UIWebView对JavaScript的支持有限,且Xamarin.Forms的WebView.Eval()方法在自定义渲染器中没有正确绑定到原生控件的JS执行能力。下面给你几个可行的解决思路:

方案一:改用WKWebView(iOS)替代UIWebView

UIWebView已被苹果弃用,WKWebView对JS的支持更完善,也更容易实现PDF的锚点跳转。

步骤1:更新自定义渲染器为WKWebView

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace DisplayPDF.iOS
{
    public class CustomWebViewRenderer : ViewRenderer<CustomWebView, WKWebView>
    {
        private WKWebView _wkWebView;

        protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var config = new WKWebViewConfiguration();
                _wkWebView = new WKWebView(Frame, config);
                SetNativeControl(_wkWebView);
            }

            if (e.NewElement != null)
            {
                var customWebView = Element as CustomWebView;
                string fileName = Path.Combine(NSBundle.MainBundle.BundlePath, $"Content/{WebUtility.UrlEncode(customWebView.Uri)}");
                Control.LoadFileUrl(new NSUrl(fileName, false), new NSUrl(NSBundle.MainBundle.BundlePath, false));
                Control.ScalesPageToFit = true;
            }
        }

        // 重写Eval方法,直接调用WKWebView的JS执行接口
        public override void Eval(string script)
        {
            _wkWebView?.EvaluateJavaScriptAsync(script);
        }
    }
}

步骤2:保留原调用逻辑即可

你的Scroll_Clicked方法无需修改,现在webView.Eval()会直接触发WKWebView的JS执行,滚动脚本可以正常工作:

private async void Scroll_Clicked(object sender, EventArgs e)
{
    webView.Eval($"window.scrollTo(0, {x});");
}

方案二:Android平台的适配(跨平台支持)

如果你的应用需要支持Android,只需确保原生WebView开启了JavaScript支持即可:

Android自定义渲染器示例

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace DisplayPDF.Droid
{
    public class CustomWebViewRenderer : ViewRenderer<CustomWebView, Android.Webkit.WebView>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var webView = new Android.Webkit.WebView(Context);
                var settings = webView.Settings;
                settings.JavaScriptEnabled = true; // 必须开启JS支持
                settings.AllowFileAccess = true;
                settings.SetSupportZoom(true);
                settings.BuiltInZoomControls = true;
                settings.DisplayZoomControls = false;
                SetNativeControl(webView);
            }

            if (e.NewElement != null)
            {
                var customWebView = Element as CustomWebView;
                string filePath = Path.Combine(Android.App.Application.Context.FilesDir.AbsolutePath, customWebView.Uri);
                Control.LoadUrl($"file://{filePath}");
            }
        }
    }
}

方案三:直接使用PDF锚点链接加载

除了JS滚动,你还可以直接构造带锚点的PDF链接(前提是PDF本身包含命名锚点,比如#chapter1),这种方式无需执行JS,兼容性更好:

// iOS平台示例
string pdfUrl = $"file://{fileName}#chapter1";
Control.LoadUrl(pdfUrl);

方案四:使用第三方PDF控件

如果以上方案都无法满足需求,可以考虑使用成熟的第三方PDF控件,比如:

  • Syncfusion PDF Viewer:支持锚点跳转、滚动、标注等丰富功能
  • Telerik UI for Xamarin:提供封装好的PDF查看组件,内置导航API

这类控件会直接封装锚点与滚动的逻辑,无需手动处理原生渲染器的细节。


内容的提问来源于stack exchange,提问作者pavel

火山引擎 最新活动