Xamarin QLPreviewController + NavigationPage 在 iOS 10 上损坏
Posted
技术标签:
【中文标题】Xamarin QLPreviewController + NavigationPage 在 iOS 10 上损坏【英文标题】:Xamarin QLPreviewController + NavigationPage broken on iOS 10 【发布时间】:2017-02-13 20:06:57 【问题描述】:将设备更新到 ios 10 后,QLPreviewController 停止以正确显示文档。它显示白屏。 我已经从应用程序中提取了示例场景。
它包含带有两个按钮的单个页面,应该加载两个不同的文档:
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:QuickLookIOS10Test"
x:Class="QuickLookIOS10Test.QuickLookIOS10TestPage">
<StackLayout Orientation="Vertical">
<Button Text="Load first doc" Clicked="OnLoadFirstClicked"/>
<Button Text="Load second doc" Clicked="OnLoadSecondClicked"/>
<Button Text="Navigate forward" Clicked="OnForwardClicked"/>
<local:QLDocumentView
x:Name="DocumentView"
BackgroundColor="Silver"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</ContentPage>
地点:
public class QLDocumentView : View
public static readonly BindableProperty FilePathProperty =
BindableProperty.Create(nameof(FilePath), typeof(string), typeof(QLDocumentView), null);
public string FilePath
get return (string)GetValue(FilePathProperty);
set SetValue(FilePathProperty, value);
涉及到一个自定义渲染器:
public class QLDocumentViewRenderer : ViewRenderer<QLDocumentView, UIView>
private QLPreviewController controller;
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
//This is a fix to prevent incorrect scaling after rotating from portrait to landscape.
//No idea why does this work :( Bug #101639
return new SizeRequest(Size.Zero, Size.Zero);
protected override void OnElementChanged(ElementChangedEventArgs<QLDocumentView> e)
base.OnElementChanged(e);
if (Control == null)
controller = new QLPreviewController();
SetNativeControl(controller.View);
RefreshView();
protected override void OnElementPropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == QLDocumentView.FilePathProperty.PropertyName)
RefreshView();
private void RefreshView()
DisposeDataSource();
if (Element?.FilePath != null)
controller.DataSource = new DocumentQLPreviewControllerDataSource(Element.FilePath);
controller.ReloadData();
protected override void Dispose(bool disposing)
base.Dispose(disposing);
if (disposing)
DisposeDataSource();
DisposeController();
private void DisposeDataSource()
var dataSource = controller.DataSource;
controller.DataSource = null;
dataSource?.Dispose();
private void DisposeController()
controller?.Dispose();
controller = null;
private class DocumentQLPreviewControllerDataSource : QLPreviewControllerDataSource
private readonly string fileName;
public DocumentQLPreviewControllerDataSource(string fileName)
this.fileName = fileName;
public override nint PreviewItemCount(QLPreviewController controller)
return 1;
public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
NSUrl url = NSUrl.FromFilename(fileName);
return new QlItem(url);
private sealed class QlItem : QLPreviewItem
private readonly NSUrl itemUrl;
public QlItem(NSUrl uri)
itemUrl = uri;
public override string ItemTitle get return string.Empty;
public override NSUrl ItemUrl get return itemUrl;
protected override void Dispose(bool disposing)
base.Dispose(disposing);
if (disposing)
this.itemUrl?.Dispose();
如果应用程序设置主页如下:
MainPage = new NavigationPage(new QuickLookIOS10TestPage());
它在 iOS 9.3 上工作,但在 iOS 10 上不工作。如果我删除 NavigationPage:
MainPage = new QuickLookIOS10TestPage();
它适用于两个 iOS 版本。
按钮点击背后的代码只是设置控件的 FilePath 属性。
Sample app demonstrating the problem
Xamarin 表单 2.3.2.127
Xamarin Studio 6.1.1(内部版本 15)
【问题讨论】:
如果您认为这曾经在 iOS 9 上工作,而现在在 iOS 10 上不再适用,您应该在 bugreport.apple.com 上告诉他们! 我仍然不知道是 iOS、Xamarin 还是我的渲染器代码问题。我无法使用 Swift 和 XCode 重现它 【参考方案1】:我也遇到过同样的问题。在 iOS10 的 QuickLook 中看起来像 something was changed or even broken,但解决方法很简单:
public class PdfViewerControlRenderer : ViewRenderer<PdfViewerControl, UIView>
private readonly bool IsOniOS10;
private UIViewController _controller;
private QLPreviewController _qlPreviewController;
public PdfViewerControlRenderer()
IsOniOS10 = UIDevice.CurrentDevice.CheckSystemVersion(10, 0);
protected override void OnElementChanged(ElementChangedEventArgs<PdfViewerControl> e)
if (e.NewElement != null)
_controller = new UIViewController();
_qlPreviewController = new QLPreviewController();
//...
// Set QuickLook datasource here
//...
if (!IsOniOS10)
_controller.AddChildViewController(_qlPreviewController);
_controller.View.AddSubview(_qlPreviewController.View);
_qlPreviewController.DidMoveToParentViewController(_controller);
SetNativeControl(_controller.View);
public override void LayoutSubviews()
base.LayoutSubviews();
_controller.View.Frame = Bounds;
_controller.View.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
_qlPreviewController.View.Frame = Bounds;
if (IsOniOS10)
_controller.View.AddSubview(_qlPreviewController.View);
_qlPreviewController.DidMoveToParentViewController(_controller);
结果:
【讨论】:
以上是关于Xamarin QLPreviewController + NavigationPage 在 iOS 10 上损坏的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin.Form与Xamarin.Android或Xamarin.IOS的区别简述
Xamarin.forms(或)xamarin.ios/xamarin.android(或)本机
Xamarin.Forms 和 Xamarin Native 有啥区别? [关闭]