Xamarin Forms自定义WebView用PDF.js加载URL PDF显示空白求助
解决Xamarin Forms自定义WebView中PDF.js加载PDF空白的问题
我来帮你排查这个PDF显示空白的问题,大概率是PDF.js资源部署、自定义WebView的渲染逻辑或者平台配置这几个环节没处理到位。咱们一步步来解决:
1. 先确认PDF.js资源是否正确部署
首先你得把PDF.js的完整预构建包(包含viewer.html、viewer.js、viewer.css以及相关的依赖文件)放到各个平台的对应目录,并且设置正确的构建属性:
- Android:把所有PDF.js文件放到
Assets文件夹,选中这些文件,在属性面板里设置Build Action为AndroidAsset。 - iOS:放到
Resources文件夹,设置Build Action为BundleResource,同时勾选Copy to Output Directory为Copy if newer。 - UWP:放到
www文件夹,设置Build Action为Content。
2. 给CustomWebView添加平台渲染器
你现在只定义了CustomWebView的绑定属性,但没有实现平台侧的渲染逻辑——默认的WebView不会自动帮你调用PDF.js的viewer来加载PDF。咱们给每个平台写个渲染器:
Android平台渲染器
[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))] namespace YourAppName.Droid.Renderers { public class CustomWebViewRenderer : WebViewRenderer { public CustomWebViewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control == null || e.NewElement == null) return; var customWebView = e.NewElement as CustomWebView; // 启用JS和DOM存储,这是PDF.js必须的 Control.Settings.JavaScriptEnabled = true; Control.Settings.DomStorageEnabled = true; // 如果PDF是http地址,而你的App是https,需要允许混合内容 if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) { Control.Settings.MixedContentMode = Android.Webkit.MixedContentMode.AlwaysAllow; } // 加载PDF.js的viewer,并传递PDF的URL参数 var encodedPdfUrl = Uri.EscapeDataString(customWebView.Uri); var viewerUrl = $"file:///android_asset/viewer.html?file={encodedPdfUrl}"; Control.LoadUrl(viewerUrl); } // 监听Uri属性变化,更新PDF内容 protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName != CustomWebView.UriProperty.PropertyName || Control == null) return; var customWebView = sender as CustomWebView; var encodedPdfUrl = Uri.EscapeDataString(customWebView.Uri); var viewerUrl = $"file:///android_asset/viewer.html?file={encodedPdfUrl}"; Control.LoadUrl(viewerUrl); } } }
iOS平台渲染器
[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))] namespace YourAppName.iOS.Renderers { public class CustomWebViewRenderer : WkWebViewRenderer { protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control == null || e.NewElement == null) return; var customWebView = e.NewElement as CustomWebView; // 启用JS Configuration.Preferences.JavaScriptEnabled = true; // 获取本地viewer.html的路径 var viewerPath = NSBundle.MainBundle.PathForResource("viewer", "html"); var viewerBaseUrl = new NSUrl(viewerPath, false).AbsoluteString; // 拼接PDF URL参数 var encodedPdfUrl = Uri.EscapeDataString(customWebView.Uri); var fullViewerUrl = $"{viewerBaseUrl}?file={encodedPdfUrl}"; Control.LoadRequest(new NSUrlRequest(new NSUrl(fullViewerUrl))); } // 监听Uri属性变化 protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName != CustomWebView.UriProperty.PropertyName || Control == null) return; var customWebView = sender as CustomWebView; var viewerPath = NSBundle.MainBundle.PathForResource("viewer", "html"); var viewerBaseUrl = new NSUrl(viewerPath, false).AbsoluteString; var encodedPdfUrl = Uri.EscapeDataString(customWebView.Uri); var fullViewerUrl = $"{viewerBaseUrl}?file={encodedPdfUrl}"; Control.LoadRequest(new NSUrlRequest(new NSUrl(fullViewerUrl))); } } }
3. 检查XAML中的布局和绑定
确保你的CustomWebView在XAML中设置了正确的布局属性,让它填满整个页面,避免因为尺寸为0导致空白:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:YourAppName" x:Class="YourAppName.MainPage"> <ContentPage.Content> <local:CustomWebView Uri="https://your-domain.com/your-document.pdf" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/> </ContentPage.Content> </ContentPage>
4. 排查其他可能的问题
- 网络权限:Android要在
AndroidManifest.xml里加<uses-permission android:name="android.permission.INTERNET"/>;如果PDF是http地址,iOS需要在Info.plist里添加App Transport Security例外(添加NSAppTransportSecurity字典,把NSAllowsArbitraryLoads设为YES)。 - CORS问题:如果PDF所在的服务器有跨域限制,可能需要在服务器端配置允许你的App域名跨域访问,或者在渲染器中添加自定义WebViewClient/WKNavigationDelegate来处理。
- PDF.js路径问题:检查
viewer.html里引用的viewer.js、viewer.css等文件的路径是否正确,比如Android里是相对路径,不要写绝对路径。
按照这些步骤调整后,应该就能正常显示PDF了。
内容的提问来源于stack exchange,提问作者waqas rauf
相关产品推荐
相关产品推荐

